PHP的扩展写法总结
在 PHP 中,扩展是一种 C 语言编写的动态链接库(.so文件或.dll文件),它能够提供一些 PHP 无法直接完成的功能,比如支持某些第三方库、提高 PHP 执行效率等。
下面将介绍如何编写 PHP 扩展,包括相关的代码示例和一些常用的扩展 API。
前置条件
在进行 PHP 扩展的编写之前,需要准备好以下工具:
- C 语言编译器:GCC、VC等
- PHP 源代码:https://www.php.net/downloads.php
扩展写法
扩展的基本结构
扩展包含两个主要的文件,一个是头文件(.h文件),另一个是源文件(.c文件)。源文件中需要包含头文件,并且实现扩展的初始化函数、定义扩展的函数等。
下面是一个基本的扩展结构:
+-- my_extension.h // 头文件
+-- my_extension.c // 源文件
编写头文件
在头文件中需要定义一些宏和函数声明,可以按照以下模板进行编写:
#ifndef MY_EXTENSION_H
#define MY_EXTENSION_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
extern zend_module_entry my_extension_module_entry;
#define phpext_my_extension_ptr &my_extension_module_entry
#endif /* MY_EXTENSION_H */
其中,zend_module_entry
结构体是 PHP 定义的用于描述模块的结构体,每个扩展都需要定义一个这样的结构体。php.h
是 PHP 预编译头文件,用于包含一些 PHP 扩展需要用到的公共头文件。
编写源文件
在源文件中需要包含头文件,并且实现扩展的初始化函数、定义扩展的函数。以下是一个简单的示例代码:
#include "php.h"
#include "my_extension.h"
static zend_function_entry my_extension_functions[] = {
PHP_FE(my_extension_hello, NULL)
PHP_FE_END
};
static PHP_MINIT_FUNCTION(my_extension)
{
return SUCCESS;
}
static PHP_MSHUTDOWN_FUNCTION(my_extension)
{
return SUCCESS;
}
static PHP_RINIT_FUNCTION(my_extension)
{
return SUCCESS;
}
static PHP_RSHUTDOWN_FUNCTION(my_extension)
{
return SUCCESS;
}
zend_module_entry my_extension_module_entry = {
STANDARD_MODULE_HEADER,
"my_extension",
my_extension_functions,
PHP_MINIT(my_extension),
PHP_MSHUTDOWN(my_extension),
PHP_RINIT(my_extension),
PHP_RSHUTDOWN(my_extension),
NULL,
NULL,
NULL,
NULL,
NULL,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_MY_EXTENSION
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
ZEND_GET_MODULE(my_extension)
#endif
在上面的示例代码中,定义了一个名为 my_extension_hello
的函数,这个函数没有参数,返回 "Hello World!"。
函数定义的格式为:PHP_FUNCTION(function_name)
,其中 function_name
是函数名。PHP_FE(function_name, arg_info)
宏可以将函数导出为扩展的 API。
编译扩展
在编写完头文件和源文件之后,可以使用以下命令来编译扩展:
phpize
./configure --enable-my_extension
make && make install
上述命令实际上执行了以下操作:
phpize
用于生成构建扩展所需的文件,例如 Makefile、configure 等。./configure --enable-my_extension
用于生成 Makefile、config.h 等文件。make && make install
用于编译并安装扩展。
使用扩展
在 PHP 中,可以使用 extension_loaded
函数来检查一个扩展是否已加载,可以使用 get_extension_funcs
函数来获取扩展的函数列表。
if (extension_loaded('my_extension')) {
$funcs = get_extension_funcs('my_extension');
var_dump($funcs);
}
示例
这里举一个引用了第三方库的扩展编写的例子。
在编写扩展前,需要先安装 libcurl
库。在 Ubuntu 系统上,可以使用以下命令来安装:
sudo apt-get install libcurl4-openssl-dev
以下是编写 curl
扩展的代码示例:
my_curl.h
#ifndef MY_CURL_H
#define MY_CURL_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include <curl/curl.h>
extern zend_module_entry my_curl_module_entry;
#define phpext_my_curl_ptr &my_curl_module_entry
PHP_FUNCTION(my_curl);
PHP_MINIT_FUNCTION(my_curl);
#endif /* MY_CURL_H */
my_curl.c
#include "my_curl.h"
static zend_function_entry my_curl_functions[] = {
PHP_FE(my_curl, NULL)
PHP_FE_END
};
static PHP_MINIT_FUNCTION(my_curl)
{
CURLcode err;
err = curl_global_init(CURL_GLOBAL_ALL);
if (err != CURLE_OK) {
php_error_docref(NULL, E_ERROR, "%s", curl_easy_strerror(err));
return FAILURE;
}
return SUCCESS;
}
static PHP_MSHUTDOWN_FUNCTION(my_curl)
{
curl_global_cleanup();
return SUCCESS;
}
static PHP_FUNCTION(my_curl)
{
CURLcode err;
CURL *curl;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com");
err = curl_easy_perform(curl);
if (err != CURLE_OK) {
php_error_docref(NULL, E_WARNING, "curl_easy_perform() failed: %s\n", curl_easy_strerror(err));
}
curl_easy_cleanup(curl);
} else {
php_error_docref(NULL, E_WARNING, "curl_easy_init() failed\n");
}
}
zend_module_entry my_curl_module_entry = {
STANDARD_MODULE_HEADER,
"my_curl",
my_curl_functions,
PHP_MINIT(my_curl),
PHP_MSHUTDOWN(my_curl),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_MY_CURL
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
ZEND_GET_MODULE(my_curl)
#endif
在上述代码中,使用 curl_global_init
函数初始化 libcurl
库,在 PHP_MINIT_FUNCTION
中实现。
在 my_curl
函数中,使用 curl_easy_init
函数创建一个 CURL
句柄,然后设置 CURLOPT_URL
选项,并使用 curl_easy_perform
函数执行请求。
常用扩展 API
这里列出一些常用的扩展 API:
PHP_FUNCTION()
:定义一个扩展函数(Function)。PHP_MINIT_FUNCTION()
:定义模块初始化函数。PHP_MSHUTDOWN_FUNCTION()
:定义模块销毁函数。PHP_RINIT_FUNCTION()
:定义请求初始化函数。PHP_RSHUTDOWN_FUNCTION()
:定义请求销毁函数。ZEND_BEGIN_MODULE_GLOBALS()
:定义模块的全局变量。ZEND_DECLARE_MODULE_GLOBALS()
:声明模块的全局变量。ZEND_GET_MODULE_GLOBALS()
:获取模块的全局变量。ZEND_MODULE_STARTUP_FUNCTION()
:定义模块启动函数。ZEND_MODULE_SHUTDOWN_FUNCTION()
:定义模块停止函数。zend_register_module_ex()
:注册一个扩展模块。zend_declare_property()
:在 PHP 类实例中声明属性。zend_parse_parameters()
:解析 PHP 函数的参数。retutn_value_*()
:返回 PHP 扩展的执行结果。zend_stream_declare_property_null()
:设置 PHP 对象的属性值。
总结
通过以上介绍,读者应该能够了解如何编写自己的 PHP 扩展。PHP 扩展的编写是 C 语言开发者应该必备的技能之一,可以借助扩展来实现 PHP 无法直接完成的功能,提高程序性能和安全性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:php的扩展写法总结 - Python技术站