PHP Extended Development Example detailed

Source: Internet
Author: User
Tags function definition ini strlen

H1. I. Automate the development of an extended framework

To the source ext directory

Help
1
./ext_skel--extname=xiami_ext
Generate a list of the following file files:
* Credits
* Experimental
* CONFIG.M4
* CONFIG.W32
* Php_xiami_ext.h
* Tests
* XIAMI_EXT.C
* xiami_ext.php

The. c file is the source file for the C language series, and the. h file is the C-Language header file, which is the file that holds functions and global variables in the C series. Subroutines are not defined in *.h. The function definition is to be placed in the *.C, and the *.h only makes the declaration. Otherwise, multiple references will occur, and a function duplication definition error occurs.

H1. Second, write function Xiami_hello

H3. 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");
}
H3.2, receiving foreign 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) br>         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
};
starts with a Zend_begin_arg_info macro definition, ends with Zend_end_arg_info (). The two macro definitions are interpreted as follows:

Zend_begin_arg_info (Name, pass_rest_by_reference):
Start parameter block definition, pass_rest_by_reference to 1 o'clock, force all parameters to reference type
Zend_end_arg_info ()

Zend_num_args () represents the number of parameters:


The type that the parameter represents
b Boolean
L Integer Integral type
D floating point floating-point type
S string string
R Resource Resources
Array of a array
O Object Instance objects
O-object instance of a specified type-specific object
Z non-specific zval any type ~
Z zval** Type
H1. Iii. Preparation of Class Xiamiclass

H3. 1. Steps

# Create a global zend_class_entry variable to store the class's entry.
# Create an array of zend_function_entry structures to store the methods contained in the class.
# registers the class in the extended Minit method.

H3. 2. Empty class

Xiami_ext.c
First, we create a zend_class_entry struct variable named Php_xiamiclass_entry, which actually stores the entry of the class we created.


Zend_class_entry *php_xiamiclass_entry;
The php_xiamiclass_entry here is a global variable in the extension source file, so that other extensions can use the class we created,
This global variable should be defined in the header file.

Next, we create an array of zend_function_entry structures that are the same as the array when the function is defined.

Const Zend_function_entry xiami_ext_methods[] = {
Php_fe_end
};
In the Minit function, you first create a XIAMI_CE variable to store the temporary class entry, and then use the Init_class_entry
The macro initializes the variable, and then uses Zend_register_internal_class () to register the class with the Zend engine.
The function returns a final class entry and assigns it to the global variable created earlier.


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;
}
H3. 3. Class method

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_method (xiamiclass,__construct);
Php_method (Xiamiclass, set_xiami_age);
Xiami_ext.c

ZEND_BEGIN_ARG_INFO_EX (arg_construct, 0, 0, 1)
Zend_arg_info (0, age)
Zend_end_arg_info ();

Zend_begin_arg_info (arg_xiami_age, 0)
Zend_arg_info (0, age)
Zend_end_arg_info ()

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 (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_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);

Zend_declare_property_null (Php_xiamiclass_entry, Zend_strl ("_age"), Zend_acc_private TSRMLS_CC);
return SUCCESS;
}
Zend_declare_property_* Series functions:


Zend_api int Zend_declare_property_null (zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC);
Use the Zend_read_property () and Zend_update_property () functions:


Zend_api zval *zend_read_property (zend_class_entry *scope, Zval *object, char *name, int name_length, Zend_bool silent TSR MLS_DC);

Zend_api void Zend_update_property (Zend_class_entry *scope, Zval *object, char *name, int name_length, Zval *value DC);
H1. 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", "the", 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 to tell PHP which global variable to modify, the data structure of our extended global variables, and the name of the global container to which these global variables are saved.
In Php_xiami_ext.h added, a pair of macros Zend_begin_module_globals () and zend_end_module_globals () are used to create a containing an age type named Zend_ Xiami_ext_globals of the structure of the body. Then you continue to declare xiami_ext_g () to get the value from a thread pool, or just get it from the global space-if you compile for a non-threading environment.

In php_xiami_ext.c you use the Zend_declare_module_globals () macro to actually instantiate Zend_xiami_ext_ The GLOBALS structure is a true global variable. Finally, in Minit, you use Zend_init_module_globals () to assign a thread-safe resource ID.

Phpinfo extended information, displaying INI 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 ();
}
H1. V. Setting 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;
}
H1. VI. Resource Processing

The resource types in PHP are implemented through a zend_rsrc_list_entry structure in the kernel:

typedef struct _ZEND_RSRC_LIST_ENTRY {
void *ptr;
int type;
int refcount;
} zend_rsrc_list_entry;
Where PTR is a pointer to the final implementation of a resource, such as a file handle, or a database connection structure. Type is a kind of tag that distinguishes different resource types. RefCount the reference count for the resource.
Resource types can be divided into common resources and persistent resources. For example MySQL common connection and persistent connection. are stored in the _zend_executor_globals structure, which contains the following two Hashtable

struct _zend_executor_globals {
...
HashTable regular_list;
HashTable persistent_list;
...
}
Regular_list saves common resources, Persistent_list saves persistent resources.
To use a resource, you first register a resource type, using 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 the value of a type member in the Id,zend_rsrc_list_entry struct body of a resource type. In the extension, this ID should be saved as a global variable to be passed to the other resource APIs.
The first and second parameters of the function, respectively, correspond to the destructors of common resources and persistent resources, the third parameter is a short name description of the resource type, generally used for error prompts, and the last parameter module_number is used internally by the engine, and when we call this function, You only need to pass a Module_number variable that has already been defined.


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 to hold 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, through 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
its first argument, Rsrc_result, is a pointer to a zval, and obviously its role is to bind PHP variables and resources.
The second parameter, Rsrc_pointer, is a pointer to the resource data.
The third parameter, Rsrc_type, is clearly the ID of the resource type returned by registering 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;
& nbsp;   }
 
     fp = fopen (filename, mode);
 
      if (fp = NULL) {
          return_false;
    }
 
     zend_register_resource (return_value, FP, Le_ MyFile);
}
To access a resource is done through 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);  & nbsp;  Zend_verify_resource (RSRC); The
first parameter, RSRC, is the variable name that corresponds to the resource value to be saved.
The second argument, which is the definition of a pointer transformation, is used to convert the resource internally to the correct type.
The third parameter, which is a corresponding resource value
, is the fourth parameter that implements the default value of the resource
Fifth parameter, and the third parameter of the ZEND_REGISTER_LIST_DESTRUCTORS_EX ()
Sixth parameter, corresponding to the Zend_ The return value of the 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) {
   &nb sp;      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 parameter of a resource ID, which returns either 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) { br>           return;
    }
 
     if (Zend_list_delete (z_resval_p (filehandle) = = failure) {
  & nbsp;       Return_false;
    }
 
     return_true;
}
Reference:

Related Article

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.