PHP extension Development--02. Package third-party extensions

Source: Internet
Author: User
Tags fread php framework php script zend

Background

Perhaps the most common PHP extensions are those that wrap third-party C libraries. These extensions include MySQL or Oracle's database service library, LIBXML2 's XML technology library, ImageMagick or GD's graphics manipulation library.

In this section, we write an extension that also uses a script to generate skeleton extensions because it saves a lot of effort. This extension wraps the standard C functions fopen (), fclose (), Fread (), fwrite (), and feof ().

Environment construction

Use the Ext_skel script to execute the following command in the ext./original code directory:

$./ext_skel --extname=myfile --proto=myfile.def
Adding extension functions

Modify header file php_myfile.h, add external interface

PHP_FUNCTION(file_open);PHP_FUNCTION(file_eof);PHP_FUNCTION(file_close);PHP_FUNCTION(file_read);PHP_FUNCTION(file_write);

Modify MYFILE.C

Myfile_functions Add external interface Information const Zend_function_entry myfile_functions[] = {Php_fe (file_open, NULL) Php_fe (file_eof, NULL) Php_fe (file_close, NULL) Php_fe (file_read, NULL) Php_fe (file_write, null) {NULL, NULL, NULL}/* must    Be the end line in myfile_functions[] */};//Add the function we want to implement at the bottom of the file//Open file 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 = vcwd_fopen (filename, mode);    if (fp = = NULL) {return_false; } zend_register_resource (Return_value, FP, le_myfile);}    Test whether the file pointer is at the end of the file Php_function (file_eof) {int argc = Zend_num_args ();    Zval *filehandle = NULL;    FILE *FP;    if (Zend_parse_parameters (argc tsrmls_cc, "R", &filehandle) ==failure) {return; } zend_fetch_resource (FP, FILE *, &Amp;filehandle,-1, "Standard-c-file", le_myfile);    if (fp = = NULL | | feof (FP) > 0) {return_true; } Return_false;}    Delete file 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;}    Read File Php_function (file_read) {int argc = Zend_num_args ();    Long size;    Zval *filehandle = NULL;    FILE *FP;    Char *result;    size_t Bytes_read;    if (Zend_parse_parameters (argc tsrmls_cc, "RL", &filehandle,&size) = = FAILURE) {return;    } zend_fetch_resource (FP, FILE *, &filehandle,-1, "Standard-cfile", le_myfile);    result = (char *) emalloc (size+1);    Bytes_read = Fread (result, 1, size, FP);    Result[bytes_read] = ' + '; Return_string (result, 0);}    Write file 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;}

Compiling the installation

$./configure  --enable-myfile && make
Test extensions
//test.php<?php    dl(‘myfile.so‘);    $fp_in = file_open("test.txt", "r") or die("Unable to open input file\n");    $fp_out = file_open("test.txt.new", "w") or die("Unable to open output file\n");    while (!file_eof($fp_in)) {         $str = file_read($fp_in, 1024);         print($str);         file_write($fp_out, $str);    }    file_close($fp_in);    file_close($fp_out);?>//test.txthello World!$php -d enable_dl=On test.phphello World!PHP Warning:  Unknown list entry type in request shutdown (0) in$cat test.txt.newhello World!

We successfully loaded the extension to read and write to the file. Successful process execution succeeded. But a mistake was reported. This problem is caused by resources not being shut down. To solve this problem, we first parse the code.

Code Literacy VCWD Macros

PHP runs on a multithreaded server and cannot use standard C file access functions. This is because the PHP script that is running in a line thread changes the current working directory, so another line thread script uses a relative path and cannot open the target file. To prevent this from happening, the PHP framework provides macros called VCWD (virtual current working directory dummy Active Directory) to replace any access function that relies on the current working directory. These macros have the same functionality as the substituted functions and are handled transparently. In some cases where there is no standard C library platform, the VCWD framework will not be supported.

Standard C Library | VCWD macro
GETCWD () | VCWD_GETCWD ()
fopen () | Vcwd_fopen
Open () | Vcwd_open ()//For two-parameter versions
Open () | Vcwd_open_mode ()//OPEN () version for three parameters
creat () | Vcwd_creat ()
ChDir () | Vcwd_chdir ()
GETWD () | VCWD_GETWD ()
Realpath () | Vcwd_realpath ()
Rename () | Vcwd_rename ()
Stat () Vcwd_stat ()
Lstat () | Vcwd_lstat ()
Unlink () | Vcwd_unlink ()
mkdir () | Vcwd_mkdir ()
RmDir () | Vcwd_rmdir ()
Opendir () | Vcwd_opendir ()
Popen () | Vcwd_popen ()
Access () | Vcwd_access ()
Utime () | Vcwd_utime ()
chmod () | Vcwd_chmod ()
Chown () | Vcwd_chown ()

Zend_register_resource New and registered resources
ZEND_REGISTER_RESOURCE(rsrc_result, rsrc_pointer, rsrc_type);

Macro Parameters | Parameter type
Rsrc_result | Zval * Resource Information set to Zend
Rsrc_pointer | Resource Data pointers
Rsrc_type | Resource ID obtained when registering a resource type

Zend_fetch_resource Getting Resources
ZEND_FETCH_RESOURCE(rsrc, rsrc_type, passed_id, default_id, resource_type_name, resource_type);

Parameters | Meaning
rsrc | The name of the variable to which the resource value is saved. It should have the same type as Rsrc_type.
Rsrc_type | The type of rsrc that is used internally to convert resources to the correct type
passed_id | Looking for the Zend resource value, Zval * *
default_id | Find the default value of a resource when not found
Resource_type_name | Registers the type name of the resource for the error message.
Resource_type | Resource type ID of the registered resource

Z_resval_p get ID by resource value
int Z_RESVAL_P(zval **)

The same is true of:

Macros | accessing Objects | Type C
Z_lval, z_lval_p, Z_LVAL_PP | Integer value | Long
Z_bval, z_bval_p, Z_BVAL_PP | Boolean value | Zend_bool
Z_dval, z_dval_p, Z_DVAL_PP | Floating point value | Double
Z_strval, z_strval_p, Z_STRVAL_PP | String Value | char *
Z_strlen, z_strlen_p, Z_STRLEN_PP | string length value int
Z_resval, Z_RESVAL_P,Z_RESVAL_PP | Resource value | Long
Z_arrval, z_arrval_p, Z_ARRVAL_PP | Union Arrays | HashTable *
Z_type, z_type_p, Z_TYPE_PP | Zval Type | Enumeration (Is_null, Is_long, is_double, is_string, Is_array, Is_object, Is_bool, Is_resource)
Z_objprop, z_objprop_p, Z_OBJPROP_PP | object Property Hash | HashTable *
Z_objce, z_objce_p, Z_OBJCE_PP | Class information for the object | Zend_class_entry

Zend_list_delete remove a resource ID from the Zend queue
int zend_list_delete(int id)

Write here can be found that the file_close call is zend_list_delete actually just the ID number of the resource is removed from the Zend engine, the real fopen open resources of C is still not released, so there is a mistake here, the following we PHP_MINIT_FUNCTION add destructors to deal with

destructor Resources

Le_myfile is a global static variable that you can understand as a file handle for a cottage. It is actually in the Zend handle of the registered resource. In the example above, we did not assign the resource to bind it, and now we are initializing it. PHP_MINIT_FUNCTION

static void myfile_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC){     FILE *fp = (FILE *) rsrc->ptr;     fclose(fp);}PHP_MINIT_FUNCTION(myfile){    /* If you have INI entries, uncomment these lines    REGISTER_INI_ENTRIES();    */    le_myfile = zend_register_list_destructors_ex(myfile_dtor,NULL,"standard-c-file", module_number);    return SUCCESS;}
ZEND_REGISTER_LIST_DESTRUCTORS_EX Registration destructor
int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number);

Parameters | Meaning
LD | destructor, called when resource is closed
PLD | destructor, called when a long connection process shuts down
type_name | Registering a resource type name
Module_number |

After modifying the installation again, no more error occurred.



From for notes (Wiz)

PHP Extension Development--02. Packages for third-party extensions

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.