加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_宿迁站长网 (https://www.0527zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php c 扩展,实现一个PHP的C扩展 [入门篇]

发布时间:2022-11-04 14:01:35 所属栏目:PHP教程 来源:转载
导读: 最近想尝试写PHP的C扩展,在《PHP7底层设计与源码实现》书中有一个PHP扩展的例子,这里动手实现了一下。
准备
Linux
PHP7
PHP7源码包 点击下载
预览
Linux查看文本行数可以使用wc -l查看,

最近想尝试写PHP的C扩展,在《PHP7底层设计与源码实现》书中有一个PHP扩展的例子,这里动手实现了一下。

准备

Linux

PHP7

PHP7源码包 点击下载

预览

Linux查看文本行数可以使用wc -l查看,现在需要将这一功能实现为PHP的自带功能。

假如有这样一个文本,中间有空行,要分析该文本行数,有些时候需要让函数输出3,有些时候让函数输出7(包括空行),可以通过配置php.ini文件保存这一配置。

然后在PHP中这样使用就好了:

开始

首先使用PHP7源码包中的ext_skel工具生成扩展的基本框架,进入源码包目录执行./ext_skel --extname=wcl,之后会在ext_skel同目录下生成一个wcl文件夹,其中wcl.c是扩展的主要源文件,php_wcl.h是头文件。

编辑config.m4,去掉PHP_ARG_ENABLE和[--enable-wcl]的注释dnl,我这边生成的config.m4默认是下面的样子,就不用改了。

编辑wcl.c文件:

/* Every user-visible function in PHP should document itself in the source */

/* {{{ proto string confirm_wcl_compiled(string arg)

Return a string to confirm that the module is compiled in */

PHP_FUNCTION(wcl)

{

size_t arg_len, len;

int argc = ZEND_NUM_ARGS();

char *arg = NULL;

if (zend_parse_parameters(argc, "s", &arg, &arg_len) == FAILURE) {

return;

}

// zend_string *strg;

// strg = strpprintf(0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "wcl", arg);

// RETURN_STR(strg);

FILE *fp;

if ((fp = fopen(arg, "r")) == NULL) {

RETURN_FALSE;

}

char ch, pre = '\n';

zend_long lcount = 0;

while ((ch = fgetc(fp)) != EOF) {

if (ch == '\n') {

lcount++;

}

pre = ch;

}

fclose(fp);

RETURN_LONG(lcount);

}

/* }}} */

/* Remove if there's nothing to do at request start */

/* {{{ PHP_RINIT_FUNCTION

*/

PHP_RINIT_FUNCTION(wcl)

{

#if defined(COMPILE_DL_WCL) && defined(ZTS)

ZEND_TSRMLS_CACHE_UPDATE();

#endif

return SUCCESS;

}

/* }}} */

/* {{{ PHP_MINFO_FUNCTION

这里是执行phpinfo()函数的输出

*/

PHP_MINFO_FUNCTION(wcl)

{

php_info_print_table_start();

php_info_print_table_header(2, "wcl support", "enabled");

php_info_print_table_end();

/* Remove comments if you have entries in php.ini

DISPLAY_INI_ENTRIES();

*/

}

/* }}} */

/* {{{ wcl_functions[]

*

* Every user visible function must have an entry in wcl_functions[].

*/

const zend_function_entry wcl_functions[] = {

PHP_FE(wcl, NULL) /* 注册上面定义的wcl函数*/

PHP_FE_END /* Must be the last line in wcl_functions[] */

};

/* }}} */

/* {{{ wcl_module_entry

*/

zend_module_entry wcl_module_entry = {

STANDARD_MODULE_HEADER,

"wcl",

wcl_functions,

PHP_MINIT(wcl),

PHP_MSHUTDOWN(wcl),

PHP_RINIT(wcl), /* Replace with NULL if there's nothing to do at request start */

PHP_RSHUTDOWN(wcl), /* Replace with NULL if there's nothing to do at request end */

PHP_MINFO(wcl),

PHP_WCL_VERSION,

STANDARD_MODULE_PROPERTIES

};

/* }}} */

计数功能主要在wcl函数中实现,无法打开文件返回false,然后按文件内容判断为换行符,计数器+1,最后返回文件行数。

之前说过对于前面的test.txt(包含多个空行),有时我们需要让函数不对空行计数php扩展,有时又需要,因此需要加载php.ini文件,将对应配置放到配置文件中由扩展加载。

编辑php_wcl.h文件:

/*

Declare any global variables you may need between the BEGIN

and END macros here:

*/

ZEND_BEGIN_MODULE_GLOBALS(wcl)

// filter_blank变量表示是否过滤空行,声明扩展内的全局变量

zend_long filter_blank;

// char *global_string;

ZEND_END_MODULE_GLOBALS(wcl)

编辑wcl.c文件

添加配置项:

/* If you declare any globals in php_wcl.h uncomment this:*/

ZEND_DECLARE_MODULE_GLOBALS(wcl)

// Remove comments and fill if you need to have entries in php.ini

PHP_INI_BEGIN()

// filter_blank变量赋默认值0

STD_PHP_INI_ENTRY("wcl.filter_blank", "0", PHP_INI_ALL, OnUpdateBool, filter_blank, zend_wcl_globals, wcl_globals)

PHP_INI_END()

/* }}} */

wcl函数做如下修改,使用WCL_G函数获取php.ini中对应配置项的值

char ch, pre = '\n';

zend_long lcount = 0;

while ((ch = fgetc(fp)) != EOF) {

if (ch == '\n') {

// filter_blank in php.ini

if (WCL_G(filter_blank) && pre == ch) {

continue;

}

lcount++;

}

pre = ch;

}

由于增加了配置项,现在要在扩展启动和销毁时对配置项做相应操作:

/* {{{ PHP_MINIT_FUNCTION

配置项的注册在该阶段完成

*/

PHP_MINIT_FUNCTION(wcl)

{

/* If you have INI entries, uncomment these lines */

REGISTER_INI_ENTRIES();

return SUCCESS;

}

/* }}} */

PHP_MSHUTDOWN_FUNCTION(wcl)

{

/* uncomment this line if you have INI entries*/

UNREGISTER_INI_ENTRIES();

return SUCCESS;

}

编译生成动态链接.so文件

phpize命令需要安装php-dev

phpize

./configure

sudo make

sudo make install

配置php.ini

执行上述过程不报错那么扩展对应的目录下会生成wcl.so文件,编辑php.ini

extension=wcl.so

[Wcl]

wcl.filter_blank = 1

到这里wcl扩展就完成了,可以重启fpm然后直接使用wcl(filename)来测试输出。

(编辑:云计算网_宿迁站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!