Detailed description of php extension development instance y

Source: Internet
Author: User
Php extension development is unlikely to be implemented by many friends because php extension development requires c. I will introduce you to a php extension development example below. i. automate the establishment of the extension framework to the ext Directory of the source code to help .. ext_skel... php extension development is unlikely to be implemented by many friends because php extension development requires c. I will introduce you to a php extension development example below.

1. automatically establish an extension framework

Go to the ext Directory of the source code to help.

./Ext_skel -- extname = xiami_ext

Generate the following file lists:

* CREDITS * EXPERIMENTAL * config.m4 * config.w32 * php_xiami_ext.h * tests * xiami_ext.c * xiami_ext.php 

. The c file is the source file of the c language series. the H file is the header file of C language, that is, the file that stores functions and global variables in C Series. the subroutine should not be defined in *. in h, the function definition should be placed in *. c, and *. h only declares. otherwise, repeated function definition errors will occur when multiple references are made.

II. Compile the xiami_hello function

1. without parameters

php_xiami_ext.h  PHP_MINIT_FUNCTION(xiami_ext); PHP_MSHUTDOWN_FUNCTION(xiami_ext); PHP_RINIT_FUNCTION(xiami_ext); PHP_RSHUTDOWN_FUNCTION(xiami_ext); PHP_MINFO_FUNCTION(xiami_ext);  PHP_FUNCTION(xiami_hello); xiami_ext.c  const zend_function_entry xiami_ext_functions[] = {     ZEND_FE(confirm_xiami_ext_compiled, NULL)     ZEND_FE(xiami_hello,        NULL)     PHP_FE_END };  ZEND_FUNCTION(xiami_hello) {     php_printf("Hello World!n"); } 

2. receive external parameters

xiami_ext.c  ZEND_BEGIN_ARG_INFO(arg_xiami_hello, 0) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO()  ZEND_FUNCTION(xiami_hello) {     char *name = NULL;     int argc = ZEND_NUM_ARGS();     int name_len;      if (zend_parse_parameters(argc TSRMLS_CC, "s", &name, &name_len) == FAILURE)         return;     php_printf("hello %s",name); }  const zend_function_entry xiami_ext_functions[] = {     ZEND_FE(confirm_xiami_ext_compiled, NULL)     ZEND_FE(xiami_hello,        arg_xiami_hello)     PHP_FE_END }; 

Start with the ZEND_BEGIN_ARG_INFO macro definition and end with ZEND_END_ARG_INFO (). The two macros are defined as follows:

ZEND_BEGIN_ARG_INFO (name, pass_rest_by_reference ):

Start parameter block definition. when pass_rest_by_reference is 1, force all parameters to be of reference type.

ZEND_END_ARG_INFO ()

ZEND_NUM_ARGS () indicates the number of parameters:

Parameter represents the type B Boolean l Integer d Floating point float s String r Resource a Array o Object instance Object O Object instance of a specified type specific type Object z Non -specific zval any type ~ Z zval ** type

III. write XiamiClass

1. steps

# Create a global zend_class_entry variable for storing class entries. # Create a zend_function_entry struct array for storing methods contained in the class. # Register a class in the extended MINIT method.

2. empty class

Xiami_ext.c

First, we create a zend_class_entry struct variable named php_xiamiclass_entry, which actually stores the portal of the class we created.

Zend_class_entry * php_xiamiclass_entry;

Here, php_xiamiclass_entry is a global variable in the extended source file. to enable other extensions to use the class we created, this global variable should be defined in the header file.

Next, we create the zend_function_entry struct array, which is the same as the array in function definition.

const zend_function_entry xiami_ext_methods[] = {     PHP_FE_END }; 

In the MINIT function, a xiami_ce variable is created to store temporary class entries. then, the variable is initialized using the INIT_CLASS_ENTRY macro, and then the class is registered to the Zend Engine using zend_register_internal_class, this function returns a final class entry and assigns it to the created global variable.

PHP_MINIT_FUNCTION(xiami_ext) {     zend_class_entry xiami_ce;     INIT_CLASS_ENTRY(xiami_ce, "XiamiClass", xiami_ext_methods);      php_xiamiclass_entry = zend_register_internal_class(&xiami_ce TSRMLS_CC);     return SUCCESS; } 

3. class methods

Resolve aggregate (xiami_ext); aggregate (plaintext); PHP_METHOD (XiamiClass ,__ construct); PHP_METHOD (XiamiClass, set_xiami_age); parameter values (arg_construct, 0, 0, 1) ZEND_ARG_INFO (0, age) values (); values (arg_xiami_age, 0) ZEND_ARG_INFO (0, age) values () PHP_METHOD (XiamiClass, _ construct) {long age; if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "l", & age) = FAILURE) {WRONG_PARAM_COUNT ;} if (age <= 0) {age = 1;} zend_update_property_long (Z_OBJCE_P (getThis (), getThis (), ZEND_STRL ("_ age"), age TSRMLS_CC ); RETURN_TRUE;} PHP_METHOD (XiamiClass, set_xiami_age) {long age; if (condition (ZEND_NUM_ARGS () TSRMLS_CC, "l", & age) = FAILURE) {WRONG_PARAM_COUNT ;} if (age <= 0) {age = 1;} zend_update_property_long (Z_OBJCE_P (getThis (), getThis (), ZEND_STRL ("_ age"), age TSRMLS_CC ); RETURN_TRUE;} PHP_MINIT_FUNCTION (xiami_ext) {parameter xiami_ce; percent (xiami_ce, "XiamiClass", percent); percent = percent (& xiami_ce TSRMLS_CC); percent (percent, percent, ZEND_STRL ("_ age"), ZEND_ACC_PRIVATE TSRMLS_CC); return SUCCESS;} zend_declare_property _ * series functions: ZEND_API int limit (zend_class_entry * ce, char * name, int name_length, int access_type TSRMLS_DC); use the functions ZEND_API zval * Transform (using * scope, zval * object, char * name, int name_length, zend_bool silent TSRMLS_DC) and zend_update_property ); ZEND_API void zend_update_property (zend_class_entry * scope, zval * object, char * name, int name_length, zval * value TSRMLS_DC );

4. Read the INI file

php_xiami_ext.h  PHP_MINIT_FUNCTION(xiami_ext); PHP_MSHUTDOWN_FUNCTION(xiami_ext); PHP_RINIT_FUNCTION(xiami_ext); PHP_RSHUTDOWN_FUNCTION(xiami_ext); PHP_MINFO_FUNCTION(xiami_ext);  PHP_FUNCTION(xiami_hello); ZEND_BEGIN_MODULE_GLOBALS(xiami_ext)     long  age; ZEND_END_MODULE_GLOBALS(xiami_ext)  #ifdef ZTS #define XIAMI_EXT_G(v) TSRMG(xiami_ext_globals_id, zend_xiami_ext_globals *, v) #else #define XIAMI_EXT_G(v) (xiami_ext_globals.v) #endif xiami_ext.c  ZEND_DECLARE_MODULE_GLOBALS(xiami_ext)  PHP_INI_BEGIN()    STD_PHP_INI_ENTRY("xiami_ext.age",      "42", PHP_INI_ALL, OnUpdateLong, age, zend_xiami_ext_globals, xiami_ext_globals) PHP_INI_END()  static void php_xiami_ext_init_globals(zend_xiami_ext_globals *xiami_ext_globals) {     xiami_ext_globals->age = 10; }  PHP_MINIT_FUNCTION(xiami_ext) {     ZEND_INIT_MODULE_GLOBALS(xiami_ext, php_xiami_ext_init_globals, NULL);     REGISTER_INI_ENTRIES();      return SUCCESS; }  ZEND_FUNCTION(xiami_hello) {     RETURN_LONG(XIAMI_EXT_G(age)); }  const zend_function_entry xiami_ext_functions[] = {     ZEND_FE(xiami_hello,        NULL)     PHP_FE_END }; 

The last three parameters of STD_PHP_INI_ENTRY are used to tell PHP which global variable to modify, the data structure of the extended global variables, and the name of the global container to which these global variables are saved.

In the content added by php_xiami_ext.h, a pair of macro values () and ZEND_END_MODULE_GLOBALS () are used to create a struct containing an age type named 'struct', and then the XIAMI_EXT_G () is declared () to get the value from a thread pool, or just from the global space-if you compile for a non-thread environment.

In php_xiami_ext.c, you use the ZEND_DECLARE_MODULE_GLOBALS () macro to instantiate the zend_xiami_ext_globals struct as a real global variable. finally, in MINIT, you use ZEND_INIT_MODULE_GLOBALS () to allocate a thread-safe resource id.

The ini information is displayed in the phpinfo extension information.

PHP_MINFO_FUNCTION(xiami_ext) {     php_info_print_table_start();     php_info_print_table_header(2, "xiami_ext support", "enabled");     php_info_print_table_end();      DISPLAY_INI_ENTRIES(); } 

5. set constants

PHP_MINIT_FUNCTION(ggg) {     zend_constant c;     char *trim_key = "xiami";     char *trim_val = "hello";     int trim_val_len,trim_key_len;      trim_key_len = strlen(trim_key);     trim_val_len = strlen(trim_val);      c.value.type = IS_STRING;     c.value.value.str.val = pestrdup(trim_val, trim_val_len+1);     c.value.value.str.len = trim_val_len;     c.flags = CONST_PERSISTENT | CONST_CS;     c.name = pestrdup(trim_key, trim_key_len+1);     c.name_len = trim_key_len+1;     c.module_number = module_number;     zend_register_constant(&c TSRMLS_CC);      return SUCCESS; } 

6. resource processing

In PHP, the resource type is implemented through a zend_rsrc_list_entry struct in the kernel:

typedef struct _zend_rsrc_list_entry {     void *ptr;     int type;     int refcount; } zend_rsrc_list_entry; 

Ptr is a pointer to the final implementation of a resource, such as a file handle or a database connection structure. type is a type tag used to distinguish different resource types, refcount indicates the reference count of a resource.

Resource types can be divided into common resources and persistent resources. for example, mysql normal connections and persistent connections are stored in the _ zend_executor_globals struct, which contains the following two HashTable.

struct _zend_executor_globals {     ...     HashTable regular_list;     HashTable persistent_list;     ... } 

Regular_list stores normal resources, and persistent_list stores persistent resources. to use resources, you must first register a resource type and use the following API functions:

ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number); 

This function returns a resource type id. the type member in the zend_rsrc_list_entry struct corresponds to this value. in expansion, this id should be saved as a global variable and passed to other resource APIs.

The first and second parameters of a function correspond to the destructor of common and persistent resources respectively. The third parameter is a brief name description of the resource type, which is generally used for error prompts, the last parameter module_number is used inside the engine. when we call this function, we only need to pass a defined module_number variable.

Static void myfile_dtor (zend_rsrc_list_entry * rsrc TSRMLS_DC) {FILE * fp = (FILE *) rsrc-> ptr; fclose (fp);} PHP_MINIT_FUNCTION (myfile) {// le_myfile is a global variable used to save the resource type id. le_myfile = zend_register_list_destructors_ex (myfile_dtor, NULL, "standard-c-file", module_number); return SUCCESS;

To create a resource, use the ZEND_REGISTER_RESOURCE () function:

ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC); #define ZEND_REGISTER_RESOURCE(rsrc_result, rsrc_pointer, rsrc_type)  zend_register_resource(rsrc_result, rsrc_pointer, rsrc_type TSRMLS_CC); 

The first parameter rsrc_result is a pointer to zval. it is clearly used to bind PHP variables to resources.

The second parameter rsrc_pointer is a pointer to the resource data.

The third parameter, rsrc_type, is obviously the resource type id returned by the above registration through the zend_register_list_destructors_ex () function.

PHP_FUNCTION(file_open){      char *filename = NULL;      char *mode = NULL;      int argc = ZEND_NUM_ARGS();      int filename_len;      int mode_len;      FILE *fp;       if (zend_parse_parameters(argc TSRMLS_CC, "ss", &filename,&filename_len, &mode, &mode_len) == FAILURE) {           return;      }       fp = fopen(filename, mode);       if (fp == NULL) {           RETURN_FALSE;      }       ZEND_REGISTER_RESOURCE(return_value, fp, le_myfile); } 

To access a resource, use the ZEND_FETCH_RESOURCE () function:

ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...); #define ZEND_VERIFY_RESOURCE(rsrc)  if (!rsrc) { RETURN_FALSE; } #define ZEND_FETCH_RESOURCE(rsrc, rsrc_type, passed_id, default_id, resource_type_name, resource_type)  rsrc = (rsrc_type) zend_fetch_resource(passed_id TSRMLS_CC, default_id, resource_type_name, NULL, 1, resource_type);    ZEND_VERIFY_RESOURCE(rsrc); 

The first parameter rsrc is the variable name corresponding to the resource value to be saved.

The second parameter is a pointer conversion definition used internally to convert resources to the correct type.

The third parameter is a corresponding resource value.

The fourth parameter is used to implement the default value of the resource.

The fifth parameter is the third parameter of zend_register_list_destructors_ex.

The sixth parameter corresponds to the return value of zend_register_list_destructors_ex.

PHP_FUNCTION(file_write){      char *buffer = NULL;      int argc = ZEND_NUM_ARGS();      int buffer_len;      zval *filehandle = NULL;      FILE *fp;       if (zend_parse_parameters(argc TSRMLS_CC, "rs", &filehandle,&buffer, &buffer_len) == FAILURE) {           return;      }       ZEND_FETCH_RESOURCE(fp, FILE *, &filehandle, -1, "standard-cfile", le_myfile);       if (fwrite(buffer, 1, buffer_len, fp) != buffer_len) {           RETURN_FALSE;      }       RETURN_TRUE; } 

To delete a resource, use the zend_list_delete () function:

ZEND_API int _zend_list_delete(int id TSRMLS_DC); #define zend_list_delete(id)  _zend_list_delete(id TSRMLS_CC) 

This function has only one resource id parameter and returns SUCCESS or FAILURE.

PHP_FUNCTION(file_close){      int argc = ZEND_NUM_ARGS();      zval *filehandle = NULL;       if (zend_parse_parameters(argc TSRMLS_CC, "r", &filehandle) == FAILURE) {           return;      }       if (zend_list_delete(Z_RESVAL_P(filehandle)) == FAILURE) {           RETURN_FALSE;      }       RETURN_TRUE; } 

Tutorial address:

Reprinted! But please include the article address ^

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.