如何编写 PHP 扩展 之 我的第一个PHP扩展

Cleey 发布于 2015/08/11 15:24
阅读 402
收藏 6
PHP

收藏!数据建模最全知识体系解读!>>>

原文链接 http://www.cleey.com/blog/single/id/771.html

这里介绍使用C 做php 的扩展,首先得有PHP安装的源码,其次以下几步:

  • 编写skel 原型
  • 生成PHP扩展框架
  • 编写自己的代码逻辑
  • 编译成PHP扩展 *.so
  • 拷贝到PHP扩展目录,重启PHP服务
  • 调用自己的PHP扩展

其实在PHP源码里面已经说明了如何编写扩展:

 vim ./php-5.6.7/README.EXT_SKEL

上面的几步除了1 ,3之外都不需要思考就能做的事,那么我们来实现一个简单的  a + b的扩展helloc函数,最终达到的目的:

<?php helloc(1022);?> // 输出为 32;

背景介绍完,现在开始:

编写skel 原型

到php安装目录下,创建文件 helloc.skel,并填写内容:

# cd  ./php-5.6.7/ext/ # vim  helloc.skel int helloc(int a int b)

生成PHP 扩展框架

在当前 ./php-5.6.7/ext/ 下执行:

# ./ext_skel --extname=helloc --proto=helloc.skel  

会生成一个 helloc 的文件夹

编写自己的代码逻辑

进入helloc ,修改config.m4文件:

# cd helloc # vim config.m4

将如下三行的 dnl 删除:

dnl PHP_ARG_WITH(helloc for helloc support
dnl Make sure that the comment is aligned: dnl [ --with-helloc Include helloc support])

修改后为:

PHP_ARG_WITH(helloc for helloc support Make sure that the comment is aligned: [ --with-helloc Include helloc support]) 

进行我们的重点,编写 a+b的逻辑。进入helloc.c 

# vim helloc.c

找到如下函数,PHP_FUNCTION(helloc),并修改为如下:

PHP_FUNCTION(helloc) { int argc = ZEND_NUM_ARGS(); long a; long b; long re; // 新增的 if (zend_parse_parameters(argc TSRMLS_CC "ll" &a &b) == FAILURE) return; re = a+b; // 新增的 RETURN_LONG(re); // 新增的 }

好了,我们的逻辑写完了。

编译成PHP扩展 *.so

只剩下编译的活了

# /usr/bin/phpize  # ./configure --with-php-config=/usr/bin/php-config # make

拷贝到PHP扩展目录,重启PHP服务

# cp modules/helloc.so /usr/lib64/php/modules/ # vim /etc/php.ini           // 为php配置文件加上扩展(文件末尾就行) extension=helloc.so # service php-fpm restart    // 这里你用的apache那么就需要重启 apache  

调用自己的PHP扩展

最后写个test.php验证自己的扩展:

# vim test.php <?php echo helloc(1022); ?> # php test.php

结果:

test.png

加载中
0
队长76
队长76
zval *arr;
char *primary_key;
long primary_key_len;
char *parent_key;
long parent_key_len;
char *nodes_name;
long nodes_name_len;
//long index;
HashTable *arr_hash;
PHP_FUNCTION(arraytree)
{
	long index;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"asssl",&arr,&primary_key,&primary_key_len,&parent_key,&parent_key_len,&nodes_name,&nodes_name_len,&index) == FAILURE){
		RETURN_NULL();
	}

	arr_hash = Z_ARRVAL_P(arr);
	array_init(return_value);
	HashPosition pos;
	zval **z_item;
	for(zend_hash_internal_pointer_reset_ex(arr_hash,&pos); zend_hash_get_current_data_ex(arr_hash,(void**) &z_item,&pos) == SUCCESS; zend_hash_move_forward_ex(arr_hash,&pos)){
		if(Z_TYPE_PP(z_item) == IS_ARRAY){
			HashTable *arr_hash_1 = Z_ARRVAL_PP(z_item);
			zval **parent_key_val;
			if(zend_hash_exists(arr_hash_1,parent_key,parent_key_len) == SUCCESS){
				if(zend_hash_find(arr_hash_1,parent_key,parent_key_len + 1,(void **) &parent_key_val) == SUCCESS){
					convert_to_long_ex(parent_key_val);
					if(Z_LVAL_PP(parent_key_val) == index){
						zval *tem_z;
						tem_z = *z_item;
						if(zend_hash_exists(arr_hash_1,primary_key,primary_key_len) == SUCCESS){
							zval **primary_key_val;
							if(zend_hash_find(arr_hash_1,primary_key,primary_key_len + 1,(void **) &primary_key_val) == SUCCESS){
								convert_to_long_ex(primary_key_val);
								zval *nodes_arr = get_tree(Z_LVAL_PP(primary_key_val));
								add_assoc_zval(tem_z,nodes_name,nodes_arr);
//								_zend_hash_index_update_or_next_insert();
							}
						}
						add_next_index_zval(return_value,tem_z);
					}
				}
			}
		}
	}
}
zval* get_tree(long i){
	HashPosition pos;
	zval **z_item;
	//ALLOC_INIT_ZVAL(arr);
	//array_init(arr);//zval *arr;
	zval *arr;
	MAKE_STD_ZVAL(arr);
	array_init(arr);
	for(zend_hash_internal_pointer_reset_ex(arr_hash,&pos); zend_hash_get_current_data_ex(arr_hash,(void**) &z_item,&pos) == SUCCESS; zend_hash_move_forward_ex(arr_hash,&pos)){
		if(Z_TYPE_PP(z_item) == IS_ARRAY){
			HashTable *arr_hash_1 = Z_ARRVAL_PP(z_item);
			zval **parent_key_val;
			if(zend_hash_exists(arr_hash_1,parent_key,parent_key_len) == SUCCESS){
				if(zend_hash_find(arr_hash_1,parent_key,parent_key_len + 1,(void **) &parent_key_val) == SUCCESS){
					convert_to_long_ex(parent_key_val);
					if(Z_LVAL_PP(parent_key_val) == i){
						zval *tem_z;
						tem_z = *z_item;
						if(zend_hash_exists(arr_hash_1,primary_key,primary_key_len) == SUCCESS){
							zval **primary_key_val;
							if(zend_hash_find(arr_hash_1,primary_key,primary_key_len + 1,(void **) &primary_key_val) == SUCCESS){
								convert_to_long_ex(primary_key_val);
								zval *nodes_arr = get_tree(Z_LVAL_PP(primary_key_val));
								//php_printf("[%s]",Z_TYPE_P(nodes_arr));
								add_assoc_zval(tem_z,nodes_name,nodes_arr);
								//zend_hash_update(tem_z->value.ht,nodes_name,nodes_name_len+1,(void *)&nodes_arr,sizeof(zval *), NULL);
							}
						}
						add_next_index_zval(arr,tem_z);
					}
				}
			}
		}
	}
	return arr;
}



0
队长76
队长76

把一个二维数组,组合成 一个 多维的 数组,树形接开关。如 array(array('id'=>1,'name'=>1,'parentid'=>0),array('id'=>2,'name'=>2,'parentid'=>1),array('id'=>3,'name'=>3,'parentid'=>2)),组合成array(array('id'=>1,'name'=>1,'parentid'=>0,'nodes'=array('id'=>2,'name'=>2,'parentid'=>1,'nodes'=>array('id'=>3,'name'=>3,'parentid'=>2)))。上面是我的代码。能跑,但是要在php代码里强求exit;。fpm进程自动杀死重启。帮我看看

0
我终于上六年级
不会的路过,我只是看看
返回顶部
顶部