In the PHP program needs to use the C code, should be the following two kinds of situation: 1 already have C code, in the PHP program to directly use 2 because of PHP performance problems, need to use C to achieve part of the function
In the first case, the most appropriate approach is to use system calls to write the existing C code as a separate program. The parameters are passed through the command line or standard input, and the results are read from the standard output. Second, a little bit of trouble is the C code written in a daemon,php program with the socket to communicate with it.
Focus on the second case, although it's OK to follow the system call method, but think about your goal of optimizing performance, so many processes are so frequent that it will certainly degrade performance. and write daemon method is feasible, but cumbersome a lot.
My simple test, the same algorithm, using C to write than PHP efficiency can be improved 500 times times. And the way to expand in PHP, can also improve 90 times (which performance loss in the parameters of the pass, I guess).
So sometimes the PHP extension is our best choice.
Here I highlight the use of C to write the PHP extension method, and do not need to recompile PHP.
First of all, find a PHP source code, PHP4 or PHP5 version of all can, and your target platform of the PHP version has no relationship.
In the source of the Ext directory can find a script named Ext_skel (Windows platform using ext_skel_win32.php) in this directory to execute./ext_skel--extname=hello (I use Hello as an example) This generates a directory hello, there are several files under the directory, you only need to care about these three: Config.m4 hello.c php_hello.h
Copy the catalogue to any place you wish, CD in, and execute phpize./configure make nothing happen, right. This is because of a missed step, open config.m4, and find the following DNL If your extension references something, use with:
... dnl otherwise use enable:
... This is where you choose your extension to use with or enable, we use with bar. Uncomment the WITH section. If you use the Vim editor as much as I do, it's easy to see that the three-letter dnl is originally annotated (this is because VIM defaults to a syntax coloring package with various file formats)
After we have modified the CONFIG.M4, we continue phpize./configure make hello.so and hello.la files are generated below modules. One is a dynamic library, the other is a static library.
Your PHP extensions are already done, and even though it hasn't implemented the functionality you want, let me start by saying how to use this extension. Ext_skel for you to generate a hello.php inside has the call example, but that example needs you to copy the hello.so to the PHP extension directory, we just want to realize their function, do not want to build a cottage version of PHP, use my following method to load it: if (! extension_loaded ("Hello")) { dl_local ("hello.so"); Function dl_local ( $extensionFile ) { // Make sure that we are able to load libraries if ( ! ( BOOL) Ini_get ( "ENABLE_DL" ) | | (BOOL) ini_get ( "Safe_mode" ) ) { die ( "dh_local (): loading extensions is not permitted./n " ); } //check To make sure the file exists &nbsP; if ( !file_exists) (DirName (__file__) . "/" . $extensionFile ) ) { die ( ) DL _local (): file ' $extensionFile ' does not exist./n ' ); } //check The file permissions if ( !is_executable dirname ( __file__) . "/" . $extensionFile ) ) { die ( "dl_local" (): file ' $extensionFile ' is not executable./n " ); } //we Figure out the path $currentDir = dirname (__file__) . "/"; $currentExtPath = ini_get ( "Extension_dir" ); $subDirs = preg_match_all ( "////" , $ currentextpath , $matches ); unset ( $matches ); //lets make sure we extracted a Valid extension path if ( ! ( BOOL) $subDirs ) { die ( "dl_local (): could not determine a valid extension path [extension_dir]./n " ); } $ Extpathlastchar = strlen ( $currentExtPath  .) - 1; if ( $extPathLastChar == strrpos ( $ currentextpath , "/" ) ) { $subDirs--; &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP} $backDirStr = ""; for ( $i = 1; $i <= $subDirs; $i ++ ) { $backDirStr .= "..."; if ( $i != $subDirs ) { $backDirStr .= "/"; } } //construct the final path to load $finalExtPath = $backDirStr . $currentDir . $extensionFile; &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;//NOW&NBSP;WE&NBSP;EXECUTE&NBSP;DL () to actually load the module if (&NBSP;!DL ( $ finalextpath ) ) { die (); } //if the module was loaded correctly, we must bow grab the module name $loadedExtensions &NBSP;=&NBSp;get_loaded_extensions (); $thisExtName = $loadedExtensions [ sizeof ( $loadedExtensions ) - 1 ]; //lastly, we return the extension Name return $thisExtName; The advantage of}//end dl_local () is that your PHP extensions can go with your PHP code and grow green.
The next concern is how to add functions, implement parameter passing, and return values
Add function steps as follows: Php_hello.h:php_function (confirm_hello_compiled);//parentheses inside the letter of the name
HELLO.C zend_function_entry hello_functions[] = {Php_fe (confirm_hello_compiled, NULL)/* Add a line here/{null, NULL, NULL}/* must is the last line in hello_functions[] */}; Php_function (confirm_hello_compiled) {//here to write function body} to achieve the function of the prototype is actually the same, with a macro php_function to package a bit, in addition, in Hello_ Functions adds a line of information that says you have this function in the module.
So are all the same function prototypes, how to distinguish between return values and parameters. I give an example: Php_function (hello_strdiff) { char *r1 = null, *r2 = NULL; int n = 0, m = 0; if (Zend_parse_parameters (Zend_num_args () TSRMLS_CC, "SS", &NBSP;&R1 , &n, &r2, &m) == failure) { return; &NBSP;&NBSP;&NBSP;&NBSP} while (n && m && *r1 ==&NBSP;*R2) { r1++; r2++; n--; m--; &NBSP;&NBSP;&NBSP;&NBSP} if (n == 0) return_long (m); if (m == 0) return_long (n); int d[n+1][m+1]; int cost; int i,j; for (i = 0; i <= n; i++) d[i][0] = i; for (j = 0; j <= m; j++) d[0][j] = j; for (i = 1; i <= n; i++) { for (j = 1; j <= m; j++) { if (R1[i-1] == r2[j-1]) cost = 0; else cost = 1; int a = min (d[i-1][j]+1 , d[i][j-1]+1); a = min (a, d[i-1][j-1]+ Cost); d[i][j] = a; &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP} } return_long ( D[n][m]); This is a two-string variance algorithm, enter the parameter two string, return integral type. The passing of the parameters look here Zend_parse_parameters (Zend_num_args () TSRMLS_CC, "SS", &r1, &n, & R2,&NBSP;&M)
Take this as a scanf to understand. The type description is shown in the following table:
Boolean |
B |
Zend_bool |
Long |
L |
Long |
Double |
D |
Double |
String |
S |
char*, int |
Resource |
R |
zval* |
Array |
A |
zval* |
Object |
O |
zval* |
Zval |
Z |
zval* |
If you want to implement optional parameters, such as a string, a floating-point, and an optional bool type, you can use "sd|b" to represent it. What's different with scanf is that for strings, you provide two variables to store, one is char *, the address of the stored string, an int, to keep the length of the string. When this is necessary, you can safely handle binary data.
So what about the return value? Use the following set of macros to represent: return_string
Return_long
Return_double
Return_bool
Return_null
Note that return_string has two parameters when you need to copy a string using Return_string ("Hello World", 1);
Otherwise use return_string (str, 0);
This involves the allocation of memory in the module, when you request the memory needs of the PHP program to release, please refer to the following table
Traditional |
non-persistent |
Persistent |
malloc (count) Calloc (count, num) |
Emalloc (count) Ecalloc (count, num) |
Pemalloc (count, 1) * Pecalloc (count, num, 1) |
StrDup (str) Strndup (str, len) |
Estrdup (str) Estrndup (str, len) |
Pestrdup (str, 1) Pemalloc () & memcpy () |
Free (PTR) |
Efree (PTR) |
Pefree (PTR, 1) |
ReAlloc (PTR, newsize) |
Erealloc (PTR, newsize) |
Perealloc (PTR, newsize, 1) |
malloc (count * num + extr) * * |
Safe_emalloc (count, num, extr) |
Safe_pemalloc (count, num, extr) |
In general, we use these non-persistent in the list.
Basically, you can start writing a php extension. From my current application, can manipulate the string is enough, so I can only introduce so much, if you want more details, such as how to deal with the PHP array, you can refer to http://devzone.zend.com/node/view/id/1022
In more detail, you can refer to the PHP manual in the "Zend API: Deep PHP Kernel" chapter but the data are in English.