Translation [PHP extension development and Embedded] Chapter 5th-Your first extension

Source: Internet
Author: User
Tags php source code zts
Your first extension

The build of each PHP extension requires at least two files: a configuration file that tells the compile time which files to build and what external libraries are needed, and at least one source file that performs the actual work.

Anatomy extension

In fact, there will usually be a second or a third configuration file, and one or more headers. For your first extension, you need to add a file of each type and work with it.

Configuration file

To get started, first create a directory named sample under the ext/directory in your PHP source directory tree. In fact, this new directory can be placed anywhere, but in order to demonstrate Win32 and static build options later in this chapter, let's start with the source code directory.

Next, go to this directory, create a file named Config.m4, and type the following:

Php_arg_enable (sample,    [Whether to ENABLE the "sample" extension],    [  enable-sample        enable "sample" Extension support])    if test $PHP _sample! = "no"; then    Php_subst (sample_shared_libadd)    php_new_extension ( Sample, sample.c, $ext _shared)  fi

This is the minimum requirement to be able to invoke the Enable-sample option when/configure. The second parameter of the php_arg_enable is displayed when the configuration file for this extension is reached during the./configure process. The third parameter is displayed as a help message when the end user executes the./configure--help.

Have you ever wondered why some extended configurations use Enable-extname, while others use With-extname? Functionally there is no difference between the two. In fact, enable means that enabling this feature does not require any third-party libraries, by contrast, with the other prerequisites for using this feature

Now, your sample extension does not need to be linked to other libraries, so you only need to use the Enable version. In the 17th chapter, "External libraries," we will describe the use of with and instruct the compiler to use additional cflags and ldflags settings.

If the end user calls the./configure using the Enable-sample option, then the local environment variable $php_sample will be set to Yes. Php_subst () is a PHP modified version of the standard autoconf Ac_subst () macro, which is required to build the extension as a shared module.

Last but not least, php_new_extension () defines the module and enumerates all the source files that must be compiled as part of the extension. If you need more than one file, it can be enumerated in the second argument using a space-delimited list, for example:

Php_new_extension (sample, sample.c sample2.c sample3.c, $ext _shared)

The last parameter corresponds to the PHP_SUBST (sample_shared_libadd) command, which is also required when building a shared module.

Header file

When using C development, it is common practice to put the type definition of the data into an external header file, which is contained by the source file. Although PHP does not require this, it is simplified when the module grows to a single source file.

In your php_sample.h header file, start with the following:

#ifndef php_sample_h/  * Prevent duplicate inclusion */  #define PHP_SAMPLE_H/    * Define Extended Properties */  #define PHP_SAMPLE_EXTNAME    " Sample "  #define Php_sample_extver    " 1.0 "* * * * * * * *    * * * * * * * * * * * * *  #ifdef have_config_h  "Config.h"  #endif/    * contains the standard header file for PHP */  #include "php.h"/    * Defines the entry point symbol, Zend Use */extern when loading this module  Zend_module_entry Sample_module_entry;  #define PHPEXT_SAMPLE_PTR &sample_module_entry    #endif/* Php_sample_h */

This header file completes two main tasks: if the extension is built using the Phpize tool (which is often used in this book), then Have_confg_h is defined so that Config.h is included in the normal way. No matter how the extension is compiled, it will contain php.h from the PHP source tree. This header file contains the PHP source code to access the majority of Phpapi to use other header files.

Next, your extension uses the ZEND_MODULE_ENTRY structure defined as external, so that when the module is loaded using EXTENSION=XXX, it can be taken by Zend using Dlopen and Dlsym ().

About the module loading process, please refer to a translator's blog < from DL (' xxx.so '); Function analysis PHP Module development > (http://blog.csdn.Net/lgg201/article/details/6584095)

The header file also contains some preprocessing that defines the information that will be used in the original file.

Source

Finally, the most important you need to create a simple source skeleton in sample.c:

#include "php_sample.h"    zend_module_entry sample_module_entry = {  #if zend_module_api_no >= 20010901       Standard_module_header,  #endif      php_sample_extname,      null,/* Functions */      NULL,/* Minit */      NULL, /* Mshutdown */      NULL,/* Rinit */      NULL,/* Rshutdown */      NULL,/* MINFO */  #if zend_module_api_no >= 2 0010901      php_sample_extver,  #endif      standard_module_properties  };    #ifdef compile_dl_sample  zend_get_module (SAMPLE)  #endif

It's that simple. These three files are everything you need to create a skeleton of a module. However, it does not have any functionality, but it is a good choice as a template to populate your functionality later in this section. But first let's see what happened.

The beginning of the line is very simple, including the header file you just created, through the extension of the PHP source tree in the other kernel header files.

Next, create the zend_module_entry structure that you defined in the header file. You should notice that the first element of zend_module_entry is a conditional expression that gives the current zend_module_api_no definition. This API number is probably php4.2.0, if you are sure that your extension will not be installed in an older version than this, you can cut off the #ifdef section and directly include the Standard_module_header element.

Consider that, in any case, it will take a little time to compile, without affecting the time required for the binary or processing of the result, so it is best to cut the condition directly in most cases. The same applies to the following version properties.

The other 6 elements are now initially set to null; You can see its purpose in the comments that follow it.

Finally, at the bottom you can see that every PHP extension that can be compiled into a shared module will have a common element. This brief condition adds a reference to the Zend when you dynamically load it. Don't care about its details, you just have to make sure it's there, otherwise the next section might not work.

Build your first extension

Now that you have all the files, it's time to compile and install them. The steps are slightly different than compiling the main PHP binaries.

Build on the *nix

The first step is to use the information in CONFIG.M4 as the last class to generate the./configure script. This can be done with the Phpize program installed when you install the main PHP binaries:

$ phpize  PHP API version:20041225  Zend Module API no:20050617  Zend Extension API no:220050617

Zend Extension API No Front 2 is not a typographical error; It corresponds to the Zend Engine 2 version number, which is generally considered to keep this API number larger than its corresponding ZE1 version.

If you look at the current directory at this point you will notice a lot more files than the 3 files just now. The Phpize program combines your extended CONFIG.M4 files with the information gathered from your PHP build and everything you need to make the compilation happen. This means you don't have to dwell on the makefile and position the PHP header. PHP has done the job for you.

The next step is simply to execute the./configure. Here you just configure your extension, so you need to do the following:

$./configure--enable-sample

Note that Enable-debug and enable-maintainer-zts are not used here. This is because phpize has taken their values from the main PHP build and applied them to your extended./configure script.

Now, build It! As with any other package, you only need to type make, and the resulting script file will handle the rest of it.

Once the build process is complete, you will get a message stating that sample.so has been compiled and placed in a directory named "modules" under the current build directory.

Build on Windows

Translators are unfamiliar with the Windows platform and are therefore skipped.

Load the built extension as a shared module

In order for PHP to find the module at the time of the request, it needs to be placed in the directory Extension_dir set in php.ini. The default php.ini is placed in/usr/local/lib/php.ini; However, this default value may vary depending on the package management system. Check the output of the php-i to see where you can find the configuration file.

If this setting in php.ini has not been modified, its value defaults to "php_home/lib/php/extensions/debug-zts-20100525", and the following debug-zts-20100525 is whether debugging is enabled, Whether ZTS is enabled, PHPAPI number. If you have not already loaded the extension, or if there are no other extensions in addition to sample.so, you can modify this value to the path of your make generation module. Otherwise, copy the resulting sample.so directly into the directory of this setting. (Note: php-i | grep extension_dir Find your Extension_dir settings)

After Extension_dir points to the correct location, there are two ways to tell PHP to load your module. The first is to use the DL () function in the script:

<?php      DL (' sample.so ');      Var_dump (Get_loaded_modules ());  ? >

If the script does not show that sample is loaded, there is something wrong with it. View the error message on the output as a clue, or refer to Error_log if the appropriate settings are in php.ini.

The second and more common way is to use the extension directive in php.ini to specify which modules to load. This directive is special in php.ini settings and can be used multiple times with different values. So if you have already set an extension in php.ini, do not enumerate in the same row using delimiters, but instead insert a new line: extension=sample.so. At this point your php.ini looks like this:

extension_dir=/usr/local/lib/php/modules/  extension=sample.so

You can now see sample in the Loaded modules list without using the DL () to run the same script, or by executing the php-m command directly.

The code for all the remainder of this chapter and subsequent chapters assumes that you have loaded the current extension as described here. If you plan to use DL (), make sure to include the Loaded Code (DL ()) in the test script.

Static Build

In the list of loaded modules, you may have noticed some modules that were included in php.ini without using the extension directive. These modules are built directly into PHP, and they are compiled into PHP as part of the main PHP program.

Static construction under *nix

Now, if you now enter the root directory of the PHP source tree, run the./configure--help, you will see that although your extension and all other modules are in the ext/directory, it is not listed as an option. This is because, at the moment, the./configure script has been generated, and your extension is not known. To regenerate the./configure and let it find your new extension, all you need to do is execute a command:

$./buildconf

If you use the product release version of PHP for development, you will find that./buildconf can't work on its own. In this case, you need to execute:./buildconf--force to circumvent some protections for./configure commands.

Now you execute./configure--help you can see that--enable-sample is an available option. At this point, you can re-execute the./configure, using all of the options you used to build the main PHP, plus--enable-sample, so that the PHP binaries that are built are complete and contain your own extensions.

Of course, it's a little early to do that. Your extension should do something in addition to taking up space.

Static build under Windows

The translator is unfamiliar with the Windows environment and is therefore skipped.

function function

The quickest link between user space and extension code is php_function (). First, at the top of your sample.c file, add the following code after #include "php_sample.h":

Php_function (Sample_hello_world)  {      php_printf ("Hello world!\n");  }

The php_function () macro function is like a normal C function definition because it expands as follows:

#define PHP_FUNCTION (name) \      void zif_# #name (internal_function_parameters)

In this case, it is equivalent to:

void Zif_sample_hello_world (Zval *return_value,      char return_value_used, zval *this_ptr tsrmls_dc)

Of course, just defining a function is not enough. The engine needs to know the address of the function and the names of the functions that should be exposed to the user space. This is done with the next block of code, which you need to add after the Php_function () Block:

Static Function_entry php_sample_functions[] = {      Php_fe (Sample_hello_world,        null)      {null, NULL, NULL}  };

The php_sample_functions vector is a simple null-ending vector that becomes larger as you add functionality to the extension. Each function you want to expose needs to be explained in this vector. Expand the Php_fe () macro as follows:

{"Sample_hello_world", Zif_sample_hello_world, NULL},

This provides the name of the new function and a pointer to its implementation function. The third parameter here is used to provide the implied information, such as some parameters that require a reference value. In the 7th Chapter, "Accept Parameters" you will see this feature.

Now you have a list of functions to expose, but still not connected to the engine. This is done by the last modification to sample.c, and the null in your sample_module_entry struct,/*/Functions/line is replaced with php_sample_functions (make sure to leave that comma).

Now, by rebuilding it in the way described earlier, testing with the-r option of the PHP command line,-R allows you to run a simple code snippet directly at the command line without creating a file:

$ Php-r ' Sample_hello_world ();

If everything is OK, you will see the output "Hello world!". Congratulations!!!

Zend Intrinsic functions

The inner function name prefix "Zif_" is the naming standard for "Zend Intrinsics", which is used to avoid possible symbolic collisions. For example, the strlen () function of user space is not implemented as void strlen (internal_function_parameters) because it conflicts with the strlen of the C library.

The zif_ prefix also does not completely avoid the problem of name collisions. As a result, PHP provides macros that can define intrinsic functions using any name: Php_named_function (); For example, Php_named_function (Zif_sample_hello_world) is equivalent to the php_function used earlier (Sample_hello_world)

When using the Php_named_function definition implementation, you can use the Php_named_fe () macro in the Function_entry vector. So if you define your own function php_named_function ( Purplefunc), use Php_named_fe (Sample_hello_world, purplefunc, null) instead of PHP_FE (Sample_hello_world, NULL).

We can see the implementation of the fopen () function in ext/standard/file.c, which is actually defined using Php_named_function (Php_if_fopen). From a user-space perspective, it doesn't care what the function is, Simply call fopen ().

function aliases

Sometimes a function may have more than one name. Recall that the normal function internal definition is the user space function name plus zif_ prefix, we can see with the PHP_NAMED_FE () macro can easily create this optional mapping.

Php_fe (Sample_hello_world,    null)  Php_named_fe (Sample_hi,    Zif_sample_hello_world,     null)

The Php_fe () macro associates the Zif_sample_hello_world of the user-space function names Sample_hello_world and php_function (Sample_hello_world). The Php_named_fe () macro associates the user-space function name Sample_hi with the same internal implementation.

Now, assuming that the Zend engine has undergone a big change, the prefix of the intrinsic function has been modified from zif_ to pif_. At this point, your extension will not work, because when you reach Php_named_fe (), Zif_sample_hello_world is not defined.

This is not a common situation, but it is very cumbersome to use Php_fname () macro to expand Sample_hello_world to avoid this problem:

Php_named_fe (Sample_hi, Php_fname (Sample_hello_world), NULL)

In this case, even if the function prefix is modified, the extended zend_function_entry will also use the macro to extend the automatic update.

Now you're ready to work, but we don't have to do that anymore. PHP exposes another macro that is specifically designed to create a function alias. The preceding example can be rewritten as follows:

Php_falias (Sample_hi, Sample_hello_world, NULL)

In fact, this is the official method of creating a function alias, which you will see frequently in the PHP source tree.

Summary

In this chapter you create a simple, working php extension and learn the steps needed to build it on the main platform. In a later chapter, you will continue to plump this extension and eventually let it contain all the features of PHP.

The PHP source tree and the tools it compiles/builds on each platform are often changed, and if some of the parts described in this chapter do not work, refer to the installation of the Php.net online manual to see the special needs of the version you are using.

The above is [translation][php extended development and Embedded] Chapter 5th-Your first extension content, more relevant content please pay attention to topic.alibabacloud.com (www.php.cn)!

  • 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.