GSoC 09 Application – PHP – Abstract Extension API and Dependency Interface

Name: Varuna Jayasiri

Proposal: Abstract Extension API and Dependency Interface

Short Description

The objective of this project is to develop functionality for PHP that will allow extensions to register a set of functions as a versioned API, since PHP does not currently handle interdependencies among PHP extensions well, which leads to various problems. This also would solve the current problem of extension load order.

Full Description

Problem

PHP does not handle interdependencies among extensions well. Configuration checks are performed during compilation to verify the availability of extensions when an extension depends on another. This leads to a number of problems, such as runtime errors and ambiguous error messages. Also, this requires the extensions to be loaded in a particular order, so that the dependent extension is loaded after the required extension; otherwise symbol not found errors will be thrown at runtime. The extension availability is checked through preprocessor macros during compilation.

More details can be found on the PHP GSoC 2009 ideas page [1].

Goal

The goal of this project is to develop a system to register and retrieve versioned API’s. This would enable extensions to expose a set of functions by registering them as an API, so that other extensions could use them. Also, extensions will be able to inquire whether certain API’s are available and what their versions are. This way the dependent extension could handle unavailability of the required extension appropriately by generating meaningful error messages or by disabling features. Also, having versioned API’s will enable backward capability.

Design

Extensions should declare API structures to be registered, which should be populated with the set of API functions. When registering an API the extension name and the version (integer) should be provided.

The API structures will be stored in a hash table indexed by extension name and version, so that API’s could be retrieved quickly.

When an extension wants to use an API from another extension it can retrieve it from the set o API’s registered using the extension name and the version. If an API is not registered then the caller extension could handle the error appropriately, either by disabling some feature or by printing meaningful error messages. The prototype of the API structure required should be declared in the caller’s headers.

When an extension requires another extension during module initialization, it is possible that the required API is not registered as the required module is yet to be initialized. To solve this, it is proposed that it should be possible to assign a call back function to be called when the required API is registered.

Proposed interface

1
int php_register_api(char *ext_name, int version, void *api, size_t size)

This function is for registering an extension API.

ext_name

Name of the extension

version

Version of the extension

api

API structure containing the set of API functions

size

Size of the API structure

Return value

0 if successful; otherwise an error code

1
int php_api_exists(char *ext_name, int version)

This function is used to check if an API exists

ext_name

Name of the extension

version

Version of the extension

Return value

PHP_EXT_AVAIL if API is present

PHP_EXT_UNAVAIL if no API by ext_name is present

PHP_EXT_NOVERSION if no API by version is present

1
int php_api_latest_version(char *ext_name)

This function is used to find the latest version of the API available

ext_name

Name of the extension

Return value

PHP_EXT_UNAVAIL if no API by ext_name is present

The version of the latest API, otherwise

1
void php_api_set_callback(char *ext_name, int version, void (*callback_func)(void **api, char *ext_name, int version))

This function is used to set a callback function to be called once the required API is registered. The call back function will be called with the extension name and version. So it is possible that call back function is set with version -1, and it will be called with the latest version and the version number of it.

ext_name

Name of the extension

version

Version of the extension

callback_func

The function to be called when the required API is registered

Example usage
Registering API

1
2
3
4
5
6
7
8
9
10
11
struct hello_ext_api {
 void (*say_hello)();
 void (*greet)(char *name)();
} api;
 
/* Set the API functions */
api.say_hello = my_say_hello;
api.greet = my__greet;
 
/* Register the API */
php_register_api("hello", 1, &api, sizeof(api));

Checking if a particular API version is available

1
2
3
4
5
6
7
8
9
10
/* Check if the version 1 is available */
int rval = php_api_exists("hello", 1);
 
if (rval == PHP_EXT_UNAVAIL) {
  zend_error(E_WARNING, "hello is not loaded or available, disabling feature");
  return NULL;
} else if (rval == PHP_EXT_NOVERSION) {
  zend_error(E_WARNING, "hello version %d is required, disabling feature", 1);
  return NULL;
}

Checking the latest version available

1
2
3
4
5
6
7
8
9
/* Get the latest version number */
int rval = php_api_latest_version("hello");
 
if (rval == PHP_EXT_UNAVAIL) {
  zend_error(E_WARNING, "hello is not loaded or available, disabling feature");
  return NULL;
} else {
  php_printf("hello version %d is available", rval);
}

Using call back function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
typedef struct hello_ext_api {
 void (*say_hello)();
 void (*greet)(char *name)();
} hello_ext_api_t;
 
/* The callback function */
void callback(void *api_void, char *ext_name, int version)
{
 hello_ext_api_t *api;
 
 if(version >= 2)
 {
  api = (hello_ext_api_t *)api_void;
 
  api->greet("Varuna");
 }
}
 
/* Set the call back function for version 2 */
php_api_set_callback("hello", 2, callback);
 
/* Or, get the latest version */
php_api_set_callback("hello", -1, callback);

Timeline

20th April to 23rd May – Community bonding period

  • Getting more familiarized with PHP core and Zend
  • Submitting the proposed API and design for suggestions
  • Getting ideas from the developer community on how this should be developed
  • Finalizing the design

23rd May to 1st July – Implementing most important features

  • The API registration and retrieval component will be developed
  • The interface for setting up the callback function will not be implemented at this stage, instead a simpler interface (e.g. php_get_api) would be provided
  • Code written will be unit tested
  • This would be a standard to be distributed for testing

1st July to 10th July – Testing the implemented section

  • The implemented features will be tested with help from the community
  • Any bugs encountered will be fixed
  • Any suggestions for improvements will be considered and implemented

10th July to 1st August – Completing the implementation of all features

  • All the functionality described above will be completed
  • Code written will be unit tested
  • Behavior of the component in various scenarios with interdependencies among extensions, will be tested thoroughly

1st August to 4th August – Buffer

  • Small buffer period so that any additional things that come up in the way could be implemented or if time taken for implementation exceeds time estimated
  • The completed extension API and dependency interface will be made available for the developer community
  • Any improvements suggested will be considered and implemented

4th August to 17th August – Testing

  • Any bug fixes will be implemented
  • All documentations will be completed
  • It will be ready for distribution at the end of testing

There is an end of semester examination during the first three weeks of June, during which I’ll only be able to work 10-15 hours of work. However, I’m pretty sure I can catch up the time lost during the two month vacation immediately after examinations.

Category (PHP, PELC, PEAR, other)

PECL

Experience

I have worked on a number of web site projects using PHP. However I do not have prior experience with writing PHP extensions or modifying PHP core source, other than what I have done while I was researching for this project.

I have quite a lot of experience with C and C++ programming, since I have been competing in International Olympiad in Informatics (Gold and 2 Silvers) and ACM ICPC regional’s using C/C++. I also compete in Topcoder [2] and other online programming competitions regularly.

I have developed an XPath module for Apache Axis2/C [3] web services engine. I was also involved in developing Sinhala Search [4] – the first Sinhala search engine. I also helped develop the automated online grading system Sathi [5].

Location

Maharagama, Sri Lanka

Preferred IRC channel or mail list

pecl-dev@lists.php.net

PHP CVS account (in case you already have one):

No CVS Account

References

[1] PHP GSoC 2009 ideas

[2] My Topcoder profile

[3] Apache Axis2/C

[4] Sinhala Search is not available currently

[5] Sathi