Extension and embedding of PHP extensions _php tutorials for extended development of--c++ classes

Source: Internet
Author: User
Today spent almost a day to study the relevant C + + extension of PHP, the first contact when a lot of places are not familiar, also met a lot of pits, here the whole process is described as follows, reference to the article is mainly http://devzone.zend.com/1435/ wrapping-c-classes-in-a-php-extension/:

A car class is now defined, and it has some member functions, and the entire extension includes the following files:
  • CONFIG.M4 Extended Configuration file
  • Php_vehicles.h Extended Header File
  • Source files for vehicles.cc extensions
  • Header files for the Car.h class
  • The source file for the Car.cc class then describes each part of the extension in the order of the files: configuration file: Config.m4
    1 php_arg_enable (Vehicles,  2     [Whether to ENABLE the "vehicles" extension],  3     [  --enable-vehicles      Enable "vehicles" extension support])  4   5 if test $PHP _vehicles! = "No", then  6     php_require_cxx ()  7     Php_subst (vehicles_shared_libadd )  8     php_add_library (stdc++, 1, Vehicles_shared_libadd)  9     php_new_extension (vehicles, vehicles.cc car.cc, $ext _shared) fi

    Line Six is a compiler that requires C + + to indicate that the extension will appear as a dynamic connection library in the form of the eighth row table is the addition of C + + library, which is similar to string and STD can be used. In the ninth line, be careful to include all the source files. Header file for class Car.h
    #ifndef vehicles_car_h  2 #define VEHICLES_CAR_H  3   4//A very simple car class  5 class Car {  6 public:  7     Car (int maxgear);  8     void Shift (int gear);  9     void Accelerate ();     brake ();     int getcurrentspeed ();     int getcurrentgear (); :     int maxgear;15     int currentgear;16     
    This is exactly the same as the header file declaration of C + +. The source file for the class car.cc source file is also a class definition that belongs to C + +
    2 #include "Car.h"  3 car::car (int maxgear) {  4     this->maxgear = maxgear;  5     this->currentgear = 1;  6     this->speed = 0;  7}  9 void car::shift (int gear) {Ten     if (Gear < 1 | | Gear > Maxgear) {one         return;12     }13     Current Gear = gear;14}16 void Car::accelerate () {     + speed + = (5 * this->getcurrentgear ());}20 void Car::brake () {21
        speed-= (5 * this->getcurrentgear ());}24 int car::getcurrentspeed () {     return speed;26}

    Next is the point: Php extension header file Php_vehicles.h
    1 #ifndef php_vehicles_h  2 #define PHP_VEHICLES_H  4 #define PHP_VEHICLES_EXTNAME  "Vehicles"  5 # Define Php_vehicles_extver   "0.1"  7 #ifdef have_config_h  8 #include "config.h"  9 #endif10 one extern "C" {#include "php.h"}14 zend_module_entry vehicles_module_entry;16 #define PHPEXT_VEHICLES_PTR &vehi CLES_MODULE_ENTRY;17 #endif/* Php_vehicles_h */
    First use the macro to determine whether the header file is already included. Then, in line fourth, give this extension an alias. The fifth line is given a version number. Note that the 11 to 13 lines are included with extern "C", because PHP is written in C, so in developing C + + Be sure to declare it when extending. Line 15th declares the entry for the entire extension, and in this entry function defines such shutdown functions as the Minit\rinit and Mshutdown Rshutdown. PHP extension Source file vehicles.cc: This file contains quite a lot of content because it hosts the task of linking the C + + class we want to the kernel of PHP. In this file, you also need to mapping the member functions in the class. To make it easy for PHP to be called directly. These features will be described in the following source code: In the first phase of coding, not related to the class-related parts, but gradually, the code here first gives the regular PHP extension of the need to do some of the operation:
    1 #include "php_vehicles.h" 2 php_minit_function (vehicles) 3 {4    return success;5}6 zend_module_entry Vehicles_ Module_entry = {7 #if zend_module_api_no >= 200109018    standard_module_header,9 #endif10    Php_vehicles_ extname,11    NULL,                  /* Functions */12    php_minit (vehicles),    NULL,/                  * Mshutdown */14    NULL, /                  * Rinit */15    NULL,/                  * Rshutdown */16    NULL,/                  * MINFO */17 #if zend_module_api_no    >= 2001090118 Php_vehicles_ extver,19 #endif20    standard_module_properties21};22 #ifdef compile_dl_vehicles23 extern "C" {zend_get_module ( Vehicles) 25}26 #endif


    The first line introduces the header file. The 2~5 line defines the module's entry function, where nothing is done first. The global variables of the module are generally initialized. Line 6th to 21st shows the connection between the extension and the Zend engine through Zend_module_entry. This is because only the Mint function is defined, so the rest of the location is null. The 22nd to 24th line is the regular project, in the extension must add, note here for C + + did the extern "C" special treatment. After this step has been completed, the extension can already be compiled. You can verify that your previous program has no errors. The procedure is as follows, and then it is not repeated.
    • Phpize
    • ./configure--enable-vehicles
    • Make
    • sudo make install
    • Add extension=vehicles.so to PHP.ini (only once)
    • Restart Apache, if it's a service sudo/etc/init.d/httpd restart
    • Then check in info.php to see if vehicles is already in the extension.
    • If you feel a lot of trouble every time you play, you can simply write a shell script to do the work. After the basic initialization is done, the connection between PHP user space and our defined C + + classes begins to be considered. This part of the code is to expose the functions in the class to the PHP user space script,
      • First you need to define a PHP class with the same name as car,
      • A set of Zend_function_entry tables is then defined to illustrate what methods in this class are intended to be introduced into the PHP user space.
      • It is important to note that the methods in the PHP user space do not necessarily have the same name as the methods in the C + + class, and you can add or subtract methods from the C + + class as needed. This is very free.

        Follow the code below to change vehicles.h
        1 #include "php_vehicles.h" 2 zend_class_entry *car_ce;3 php_method (car, __construct) {}5 Php_method (car, shift) {}7 PH P_method (car, accelerate) {}9 Php_method (car, brake) {}11 Php_method (car, getcurrentspeed) {}13 Php_method (car, Getcurre Ntgear) {}15 Zend_function_entry car_methods[] = {Php_me (car, __construct, NULL, Zend_acc_public | Zend_acc_ctor) Php_me (car, shift, NULL, zend_acc_public) Php_me (car, accelerate, NULL, ZEND_ACC _public) Php_me (car, brake, NULL, zend_acc_public) Php_me (car, getcurrentspeed, NULL, Zend_acc_publi C) Php_me (Car, getcurrentgear, NULL, zend_acc_public), {null, NULL, null}23};24 php_minit_function (vehicles) Zend_class_entry ce;27 init_class_entry (CE, "Car", car_methods); car_ce = Zend_register_internal_class ( &ce tsrmls_cc); return success;30}31 zend_module_entry vehicles_module_entry = {#if zend_module_api_no ; = 2001090133 Standard_module_header,34 #endif35 php_vehicles_extname,36 NULL,/* Functions */37 Php_minit (vehicles),/* Minit */3 8 NULL,/* Mshutdown */39 NULL,/* Rinit */40 NULL,/* Rshutdown */41 NULL,/* MIN  FO */42 #if zend_module_api_no >= 2001090143 php_vehicles_extver,44 #endif45 standard_module_properties46};47 #ifdef compile_dl_vehicles48 extern "C" {zend_get_module (vehicles)}51 #endif


        The first is to define a zend_class_entry in the second row, which is initialized at minit time. The 3~13 line gives the version of the PHP method that the member functions of the C + + class convert to, and then adds the corresponding implementation. 15~ The 23 row defines where the function entry zend_function_entry,php method is defined. You can also declare a set of aliases that you define yourself. (How to define, how to embody?) 24~30 gives the new module initialization Minit function:
        • The Init_class_entry function links the entry of the class to the method of the class previously in the Zend_function_entry, and belongs to the initialization of the class.
        • Car_ce = Zend_register_internal_class (&ce tsrmls_cc), registering classes, adding classes to Class table, the 31~51 line is no different from the previous module entry.

          Now that a set of PHP functions with the same name as a C + + class member function is declared, the next thing to do is to link the two: each C + + class instance must correspond to a PHP class instance, and one way to do this is to use a structure to track existing C + + and PHP class instances. In order to do this, you need to write your own object processor, in PhP5, an object is composed of a handle (which allows the Zend engine to locate the ID of your class), a function table, and a set of processors. Processors can be overridden at different stages of the object's declaration cycle to implement different functions. So on the basis of the previous code, first add an object handler:
          1  #include "car.h" 2  zend_object_handlers car_object_handlers;3  struct Car_object {4     zend_object std ; 5     Car *car;6  };



          This car_object structure will be used to track instances of C + + and then associate with Zend_object. Before Php_method's declaration, the following two methods need to be added:
          1  void car_free_storage (void *object tsrmls_dc) 2  {3    car_object *obj = (Car_object *) object;4    Delete obj->car; 5    Zend_hash_destroy (obj->std.properties), 6    free_hashtable (obj->std.properties), 7    efree (obj); 8  }9  zend_object_value car_create_handler (zend_class_entry *type tsrmls_dc)  {zval    *tmp;12    zend_object_value retval;13    car_object *obj = (Car_object *) emalloc (sizeof (Car_object));    memset ( obj, 0, sizeof (car_object));    obj->std.ce = type;16    alloc_hashtable (obj->std.properties);    Zend_hash_init (obj->std.properties, 0, NULL, zval_ptr_dtor, 0);    zend_hash_copy (Obj->std.properties, &type->default_properties,19        (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof (Zval *)); 20    retval.handle = zend_objects_store_put (obj, null,21        car_free_storage, NULL tsrmls_cc);    Retval.handlers = &car_object_handlers;23    return retval;24}


          The module initialization function Minit then needs to be modified as follows:
          Php_minit_function (vehicles) (    zend_class_entry ce;28    init_class_entry (CE, "Car", car_methods); 29    car_ce = Zend_register_internal_class (&ce tsrmls_cc);    car_ce->create_object = Car_create_handler;    memcpy (&car_object_handlers,32        zend_get_std_object_handlers (), sizeof (zend_object_handlers)); 33    car_object_handlers.clone_obj = null;34    


          Here we see line 30th, first calling Car_create_handler to create a create_object processor. When calling Car_create_handler, pay attention to a big pit, that's the 18th line. Here is properties_info in the new version of $type->default_properties,php. This compilation error after comparing the source code to know how to change.
          • 13~15 has applied space to a car_object and completed the initialization. At the same time, the corresponding zend_class_object of obj and the input type () are connected, that is, the Zend object initialized in Minit is bound to the car_object structure.
          • After the binding has been completed, 16~19 continues with the copy process.
          • The 20~21 line adds obj to the Zend object, defines the function car_free_storage at the time of the destruction using the function pointer, and produces a handle to the object obj
          • The 31st line gives the processor handlers the corresponding Zend_object_handlers value (it is not clear here)


            Now in the class constructor of PHP, you should read the user's arguments and pass them to the C + + constructor. Once a C + + class instance is created, it is possible to grab the Car_object pointer from the Zend object store and set the car value in the struct body. In this case, the Zend object instance and the car instance of C + + are bound together.
            1  php_method (Car, __construct) 2  {3     long maxgear;4    Car *car = null;5    zval *object = Getthis (); 6    if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "L", &maxgear) = = FAILURE) {7        return_null (); 8    } 9    car = new Car (maxgear),    car_object *obj = (Car_object *) Zend_object_store_get_object (object tsrmls_cc); 11< C10/>obj->car = car;12  }


            You can get an instance of the C + + class by calling the Zend_object_store_get_object function. and the following two functions are the same:
            Php_method (accelerate) {    Car *car;    Car_object *obj = (Car_object *) Zend_object_store_get_object (        getthis () tsrmls_cc);    Car = obj->car;    if (car! = NULL) {        car->accelerate ();    }} Php_method (getcurrentspeed) {    Car *car;    Car_object *obj = (Car_object *) Zend_object_store_get_object (        getthis () tsrmls_cc);    Car = obj->car;    if (car! = NULL) {        Return_long (car->getcurrentspeed ());    }    Return_null ();}



            Well, so far the whole framework has been set up. Do not forget to reconfigure the compilation, and then use the following PHP code can be tested:
            /Create a 5 gear Car$car = new car (5);p rint $car->getcurrentspeed ();  Prints ' 0 ' $car->accelerate ();p rint $car->getcurrentspeed (); Prints ' 5 ' If You can run the this script, congratulations, you ' ve just created a PHP extension that wraps a C + + class.


            If the output is consistent with the logo, then the whole process will be successful, congratulations!

            http://www.bkjia.com/PHPjc/621614.html www.bkjia.com true http://www.bkjia.com/PHPjc/621614.html techarticle today spent almost a day to study the relevant C extension of PHP, the first contact when a lot of places are not too familiar, also met a lot of pits, here the whole process described as follows, reference to the text ...

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.