我们在开发php的时候可能会遇到调用so的问题,本篇介绍如何编写自己的动态链接库提供给php使用。
创建一个 .so 文件
1. 创建hello.c
int hello_add(int a, int b)
{
return a + b;
}
2. 编译
$ gcc -O -c -fPIC -o hello.o hello.c
$ gcc -shared -o libhello.so hello.o
$ su
# echo /usr/local/lib > /etc/ld.so.conf.d/local.conf
# cp libhello.so /usr/local/lib
# /sbin/ldconfig
3. 验证是否正确加载
创建 hellotest.c
#include <stdio.h>
int main()
{
int a = 3, b = 4;
printf("%d + %d = %d\n", a, b, hello_add(a,b));
return 0;
}
执行
$ gcc -o hellotest -lhello hellotest.c # -lhello 编译时加入动态so 文件
$ ./hellotest
3 + 4 = 7
在 CentOS 下可以正常编译
4. 下载php 源码
http://php.net/get/php-5.6.1.tar.bz2/from/a/mirror
进入ext
$ ./ext_skel --extname=hello
$ cd hello
5. 修改 config.m4
去掉第16行和第18行的注释(注释符号为 dnl )
16: PHP_ARG_ENABLE(hello, whether to enable hello support,
17: dnl Make sure that the comment is aligned:
18: [ --enable-hello Enable hello support])
$ phpize
6. 修改php_hello.h
在文件后尾添加
PHP_FUNCTION(hello_add);
7. 编辑hello.c
zend_function_entry hello_functions[] = {
PHP_FE(confirm_hello_compiled, NULL) /* For testing, remove later. */
PHP_FE(hello_add, NULL) /* 此处添加要实现的方法 */
{NULL, NULL, NULL} /* Must be the last line in hello_functions[] */
};
//文末,添加具体实现
PHP_FUNCTION(hello_add)
{
longint a, b;
longint result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) {
return;
}
result = hello_add(a, b);
RETURN_LONG(result);
}
类型指定符 | 对应的C类型 | 描述 |
l | long | 符号整数 |
d | double | 浮点数 |
s | char *, int | 二进制字符串,长度 |
b | zend_bool | 逻辑型(1或0) |
r | zval * | 资源(文件指针,数据库连接等) |
a | zval * | 联合数组 |
o | zval * | 任何类型的对象 |
O | zval * | 指定类型的对象。需要提供目标对象的类类型 |
z | zval * | 无任何操作的zval |
8. 编译安装
$ phpize
$ ./configure --with-php-config=/www/server/php/56/bin/php-config
$ make clean # 清除编译
$ make LDFLAGS=-lhello #-lhello 表示加载 动态库 libhello.so 文件
$ sudo make install
在php.ini
加入extension=hello.so
9. 测试
php -r"echo hello_add(3, 4);"
//输出7
或者使用php hello.php