linux c 开发php扩展

用C重写一个PHP的系统函数ip2long()解决ip2long在32位与64位系统下值不同的问题(该问题是因为32位与64位的整形范围不同导致的,具体原因请google)。
我们新的ip2long固定返回32位有符号整数,范围-2147483648 到 2147483647,与32位系统相同。
我们的扩展名称为 myip,函数名为 ip2long32
扩展的功能与名称都OK了,现在按流程进行开发。

1 查看php是否编译成功

c1.png

2 开发流程

c2.png

3 进入源码目录

cd /home/users/chromev/php-5.5.7/ext

./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]]
           [--skel=dir] [--full-xml] [--no-help]

  --extname=module   module is the name of your extension(模块名,会在当前目录创建一个该名称子目录)
  --proto=file       file contains prototypes of functions to create(函数原型定义文件)
  --stubs=file       generate only function stubs in file
  --xml              generate xml documentation to be added to phpdo     c-cvs
  --skel=dir         path to the skeleton directory(设置骨架生成的目录,不设置该项则默认在ext/extname下)
  --full-xml         generate xml documentation for a self-contained extension
                     (not yet implemented)
  --no-help          don't try to be nice and create comments in the code
                     and helper functions to test if the module compiled (生成的代码中不显示各种帮助注释)

执行生成框架

./ext_skel --extname=myip --proto=myip.pro

进入目录

cd myip
ls -al

c3.png

4. 修改myip.pro,添加

int ip2long32(string ip)

这意味着我们的扩展中有一个函数,返回值为int型,输入为string。

5. 修改config.m4

vim config.m4
c4.png

6. C编码

vim myip.c
c5.png
图中就是扩展骨架工具根据我们提供的函数原型生成的对应函数,此处有几个需要注意的地方:

1). PHP_FUNCTION:是PHP核心定义的一个宏,与ZEND_FUNCTION相同,用于定义扩展函数,实际生成的函数名称为zif_ip2long32。

2). zend_parse_parameters:由于PHP为弱类型语言,而C是强类型,因此需要使用该函数用于接收PHP传入的参数,并进行一定的类型转换,将PHP的变量转为C语言能够辨认的类型。

  zend_parse_parameters函数的原型如下:

  zend_parse_parameters(int num_args TSRMLS_CC, char *type_spec, …);

num_args:传递给函数的参数个数。通常的做法是使用宏 ZEND_NUM_ARGS()。

3)TSRMLS_CC:
线程安全,总是传递TSRMLS_CC宏。
详解:http://www.54chen.com/php-tech/what-is-tsrmls_cc.html
type_spec:第三个参数是一个字符串,指定了函数期望的参数类型

4):需要随参数值更新的变量列表

函数修改
c7.png

7 编译,配置,测试

在ext当前目录执行

     /usr/local/webserver/php/phpize
     ./configure -with-php-config=/usr/local/webserver/php/bin/php-config
     make && make install

出现 

Installing shared extensions:     /usr/local/webserver/php/lib/php/extensions/no-debug-non-zts-20121212/

查看

ls /usr/local/webserver/php/lib/php/extensions/no-debug-non-zts-20121212/

是否存在 myip.so

添加扩展

vim php.ini
extension_dir = "/usr/local/webserver/php/lib/php/extensions/debug-non-zts-20090626/"
extension = myip.so

退出保存,并重启php,如果是使用Phpfpm的话可以执行如下命令:

kill -USR2 `cat /usr/local/webserver/php/var/run/php-fpm.pid`

看下扩展是否正常载入:

php -m|grep myip

测试

php -r "var_dump(ip2long32('192.168.1.1'));"
int(-1062731519)

php -r "var_dump(ip2long('192.168.1.1'));"  
int(3232235777)

如上所示,ip2long32输出的是32位有符号整数,而ip2long输出的是64位无符号整数,大功告成!

标签: php, linux

添加新评论