您的位置:首页 > 编程语言 > PHP开发

构建一个简单的php扩展

2016-12-09 15:55 656 查看

构建一个简单的php扩展

基本步骤

1  ./ext_skel --extname=myext

2  修改 config.m4文件
去掉这几行前面的dl
PHP_ARG_ENABLE(myext, whether to enable myext support,
Make sure that the comment is aligned:
[  --enable-myext           Enable myext support])
3  ./phpize生成扩展的模块

4 修改php_myext.h文件 新增一行(定义函数) PHP_FUNCTION(myext_self_concat);

5 在mytexc.c中注册函数
const zend_function_entry myext_functions[] = {
PHP_FE(myext_self_concat,NULL)
PHP_FE(confirm_myext_compiled,  NULL)
PHP_FE_END
};

6 编写函数代码
PHP_FUNCTION(myext_self_concat){
char *arg = NULL;
int arg_len, len;
char *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"s", &arg, &arg_len) == FAILURE) {
return;
}
php_printf("myext_self_concat\n");
RETURN_TRUE;
}
7 ./configure && make && make install

8 在php的配置上加上扩展
如果没有配置文件自己加一个比如我的/Users/kang/Documents/CProject/php566/lib/php.ini
/Users/kang/Documents/CProject/software/bin/php -m 查看模块

9 运行扩展中的函数

查看扩展的函数
/Users/kang/Documents/CProject/software/bin/php -r "print_r(get_extension_funcs('myext'));"

使用扩展的函数
/Users/kang/Documents/CProject/software/bin/php -r  "myext_self_conc


构建一个简单的扩展需要掌握的知识

在网上找了一些知识,我觉得条目不够清楚,所以做了一个整理

对php的运行机制有个基本的理解

一切的php都从SAPI Server Application Programming Interface开始运行

在SAPI下面是各种模式 例如cli

php的执行流程,以我的扩展为例子:
PHP_MINIT(ext_start1),
PHP_MSHUTDOWN(ext_start1),
PHP_RINIT(ext_start1),
PHP_RSHUTDOWN(ext_start1),

在多进程挂起的情况下可能是:

PHP_MINIT 后不会PHP_RSHUTDOWN
然后PHP_RINIT,加载脚本,执行程序,最后PHP_MSHUTDOWN

php的线程安全:
抽象层:TSRM(Thread Safe Resource Management)
线程安全模块和非线程模块有点不一样,我觉得主要是锁的问题,如果是多线程模式,
资源需要加锁,抽象层就是锁等等进行了封装和集中处理


对php里面变量的表示有个基础的了解

每个变量都会做些类似的转换

struct _zval_struct {
zvalue_value value; /* 变量的值 */
zend_uint refcount__gc;
zend_uchar type;    /* 变量当前的数据类型 */
zend_uchar is_ref__gc;
};
typedef struct _zval_struct zval;

//在Zend/zend_types.h里定义的:
typedef unsigned int zend_uint;
typedef unsigned char zend_uchar;

typedef union _zvalue_value {
long lval;  /* long value */
double dval;    /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht;  /* hash table value */
zend_object_value obj;
} zvalue_value;


函数接收参数

zend_parse_parameters() 读取函数的值
TSRMLS_CC TSRM表示Thread Safe Resource Manager,可能跟线程安全有关

例如:
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"l", &foo) == FAILURE
TSRMLS_CC  TSRM相关的宏---这个坑待我以后看看
ZEND_NUM_ARGS()表示参数的个数

type_spec是格式化字符串,其常见的含义如下:
参数   代表着的类型
b   Boolean
l   Integer 整型
d   Floating point 浮点型
s   String 字符串
r   Resource 资源
a   Array 数组
o   Object instance 对象
O   Object instance of a specified type 特定类型的对象
z   Non-specific zval 任意类型~
Z   zval**类型
f   表示函数、方法名称,PHP5.1里貌似木有... ...

读取字符串变量:

char *name;
int name_len;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",&name, &name_len) == FAILURE)
{
RETURN_NULL();
}


为变量分配内存

C语言原生函数
void *malloc(size_t count);
void *calloc(size_t count);
void *realloc(void *ptr, size_t count);
void *strdup(void *ptr);
void free(void *ptr);

PHP内核封装后的函数 -- 带p表示永久性
void *emalloc(size_t count);
void *pemalloc(size_t count, char persistent);

void *ecalloc(size_t count);
void *pecalloc(size_t count, char persistent);

void *erealloc(void *ptr, size_t count);
void *perealloc(void *ptr, size_t count, char persistent);

void *estrdup(void *ptr);
void *pestrdup(void *ptr, char persistent);

void efree(void *ptr);
void pefree(void *ptr, char persistent);


返回结果

咱们可能任务返回结果一遍得这么写

ZEND_FUNCTION(sample_long_wrong)
{
zval *retval;

MAKE_STD_ZVAL(retval);
ZVAL_LONG(retval, 42);

return retval;
}


其实我们可以,php已经帮我们做好了上述的工作

PHP_FUNCTION(sample_long)
{
RETVAL_LONG(42);
//展开后相当与ZVAL_LONG(return_value, 42);
return;
}


参考资料:

TIPI项目:http://www.php-internals.com/book/
挖路项目:http://www.cunmou.com/phpbook/
鸟哥的博客 http://www.laruence.com/2009/04/28/719.html 我的博客 http://www.beckbi.cn/?p=328
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: