This article mainly introduces the implementation method for php to call C code. If you need it, please refer to it and hope to help you.
This article mainly introduces the implementation method for php to call C code. If you need it, please refer to it and hope to help you.
C code must be used in php programs. There are two possible cases:
1. You already have C code. You can use it directly in a php program.
2 due to php performance problems, some functions need to be implemented using C.
In the first case, the most appropriate method is to use system to call the existing C code as an independent program. Parameters are passed in through the command line or standard input, and the results are read from the standard output. Second, the less troublesome method is to write the C code as a daemon, And the php program uses socket to communicate with it.
Focus on the second case. Although the method called by the system can be used, but think about your purpose to optimize the performance, so frequent initiation of so many processes will certainly reduce the performance. The method for writing daemon is feasible, but complicated.
In my simple test, the same algorithm, using C for writing is 500 times more efficient than using php. The php extension method can also be improved by more than 90 times (the performance loss is due to parameter transfer, I guess ).
So sometimes php extension is our best choice.
Here I will introduce how to write php extensions in C without re-compiling php.
First, find a php source code, which can be php4 or php5. It has nothing to do with the php version of your target platform.
In the ext directory of the source code, you can find the script named ext_skel (ext_skel_win32.php is used on windows)
Execute./ext_skel -- extname = hello in this directory (I use hello as an example)
At this time, a directory "hello" is generated, which contains several files. You only need to care about these three files: config. m4 hello. c php_hello.h.
Copy the directory to any place you want and run the cd command in sequence.
Phpize
/Configure
Make
Nothing happened, right?
This is because a step is missing. Open config. m4 and find the following
Dnl If your extension references something external, use:
..
Dnl Otherwise use enable:
..
This is to let you choose whether your extension uses with or enable. Let's use. Uncomment the part.
If you use the vim editor like me, you will easily find that the three dnl letters originally represent annotations (this is because vim uses syntax coloring packages of various file formats by default)
After we modify config. m4, continue
Phpize
/Configure
Make
In this case, the hello. so and hello. la files are generated under modules. One is a dynamic library and the other is a static library.
Your php extension has been completed. Although it has not implemented the functions you want, let me first talk about how to use this extension! Ext_skel generates a hello. php contains a call example, but you need to set hello in that example. so copy to the extension directory of php. We only want to implement our own functions and do not want to create a cottage version of php. Use the following method to load it:
The Code is as follows:
If (! Extension_loaded ("hello ")){
Dl_local ("hello. so ");
}
Function dl_local ($ extensionFile ){
// Make sure that we are ABLE to load libraries06. 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 exists11. if (! File_exists (dirname (_ FILE _). "/". $ extensionFile )){
Die ("dl_local (): File '$ extensionFile' does not exist./n ");
}
// Check the file permissions16. if (! Is_executable (dirname (_ FILE _). "/". $ extensionFile )){
Die ("dl_local (): File '$ extensionFile' is not executable./n ");
}
// We figure out the path21. $ currentDir = dirname (_ FILE __)."/";
$ CurrentExtPath = ini_get ("extension_dir ");
$ SubDirs = preg_match_all ("//", $ currentExtPath, $ matches );
Unset ($ matches );
// Lets make sure we extracted a valid extension path27. if (! (Bool) $ subDirs ){
Die ("dl_local (): cocould not determine a valid extension path [extension_dir]./n ");
}
$ ExtPathLastChar = strlen ($ currentExtPath)-1;
If ($ extPathLastChar = strrpos ($ currentExtPath ,"/")){
$ SubDirs --;
}
$ BackDirStr = "";
For ($ I = 1; $ I <= $ subDirs; $ I ++ ){
$ BackDirStr. = "..";
If ($ I! = $ SubDirs ){
$ BackDirStr. = "/";
}
}
// Construct the final path to load46. $ finalExtPath = $ backDirStr. $ currentDir. $ extensionFile;
// Now we execute dl () to actually load the module49. if (! Dl ($ finalExtPath )){
Die ();
}
// If the module was loaded correctly, we must bow grab the module name54. $ loadedExtensions = get_loaded_extensions ();
$ ThisExtName = $ loadedExtensions [sizeof ($ loadedExtensions)-1];
// Lastly, we return the extension name58. return $ thisExtName;
} // End dl_local ()
The advantage is that your php extension can follow your php code to implement green extension.
Another concern is how to add functions, implement parameter transfer, and return values.
To add a function, follow these steps:
Php_hello.h:
PHP_FUNCTION (confirm_hello_compiled); // enter the function name in the brackets.
Hello. c
Zend_function_entry hello_functions [] = {
PHP_FE (confirm_hello_compiled, NULL)/* Add a row here */
{NULL, NULL, NULL}/* Must be the last line in hello_functions [] */
};
PHP_FUNCTION (confirm_hello_compiled)
{// Write the function body here
}
The prototype of the function to be implemented is actually a sample. The macro PHP_FUNCTION is used for packaging. In addition, a line of information is added to hello_functions, indicating that you have this function in this module.
So they all have the same function prototype. How can we distinguish between return values and parameters?
Here is an example:
The Code is as follows: