前面实现的函数参数只是简单的类型,但是如何传输结构体和数组呢?
通过看参考资料《Zend_API:深入_PHP_内核》和《PHP_Extension_Writing之中文版》基本实现了这个功能。
一、 C库的代码
定义了结构体:
struct bsEmaplist
{
long ID;
char name[128];
long pID;
};
这个函数是生成 usrID,并传输给 PHP 代码。
long bsGetUserID(char *name, char *pw, char *usrID)
{
if(name == NULL || pw == NULL || usrID == NULL)
{
return -1;
}
sprintf(usrID, “%s-%s-%s”, name, pw, “testID”);
return 0;
}
这个函数把一些信息传输给上级 PHP 。
这些信息为 struct bsEmaplist 结构体数组也 long 型的数据。
long bsGetEmaplist(char *usrID, long pID, struct bsEmaplist * p, long *num)
{
int i;
if(usrID == NULL || p == NULL || num == NULL)
{
return -1;
}
for(i = 0; i < 5; i++)
{
p[i].ID = i;
p[i].pID = i+1;
sprintf(p[i].name, “emapname_%d”, i);
}
*num = 5;
return 0;
}
二、 具体扩展函数的代码
PHP_FUNCTION(bsGetUserID)
{
char *name, *pw, *usrID;
int name_len, pw_len, usrID_len;
if(ZEND_NUM_ARGS() != 3)
WRONG_PARAM_COUNT;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “sss” , &name, &name_len, &pw, &pw_len, &usrID, &usrID_len)
== FAILURE)
{
RETURN_NULL();
}
bsGetUserID(name, pw, usrID);
php_printf(“Username: %sn”, name);
php_printf(“Password: %sn”, pw);
php_printf(“usrID: %sn”, usrID);
RETURN_TRUE;
}
PHP_FUNCTION(bsGetEmaplist)
{
zval * tmp;
zval * zlist, znum;
struct bsEmaplist emaplist[20];
long num;
int i;
char * usrID;
long usrID_len, pID;
if(ZEND_NUM_ARGS() != 4)
WRONG_PARAM_COUNT;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “slzz” , &usrID, &usrID_len, &pID, &zlist, &znum) == FAILURE
)
{
RETURN_NULL();
}
bsGetEmaplist(usrID, pID, emaplist, &num);
MAKE_STD_ZVAL(tmp);
if(object_init(tmp) != SUCCESS)
{
RETURN_NULL();
}
for(i = 0; i < num; i++)
{
MAKE_STD_ZVAL(tmp);
if(object_init(tmp) != SUCCESS);
php_printf(“%d %d %sn”, emaplist[i].ID, emaplist[i].pID, emaplist[i].name);
add_property_long(tmp, “ID”, emaplist[i].ID);
add_property_long(tmp, “pID”, emaplist[i].pID);
add_property_string(tmp, “name”, emaplist[i].name, 1);
add_index_zval(zlist, i, tmp);
}
zval_copy_ctor(zlist);
RETURN_TRUE;
}
上面主要用到的函数:
ZEND_NUM_ARGS() 检查参数个数
zend_parse_parameters() 解析参数,相当于 sscanf() 函数 ,具体看 上面的参考资料
object_init() 初始化对象
MAKE_STD_ZVAL()
add_property_long() 对象的操作函数,添加 long 型的成员
add_property_string() 对象的操作函数,添加 字符串 型的成员
add_index_zval() 数组操作函数,添加对象到数组中
zval_copy_ctor() 拷贝函数,因为上面赋值只是进行索引,到PHP层不能访问这个内存,所以需要拷贝
三、 测试代码
<?php
dl(“omatetest.so”);
/*
error_reporting(E_ALL);
$userId = “”;
$getUserId = bsGetUserID(“admin”,”123456″, $userId);
var_dump($getUserId.”*********”.$userId);
echo “<br/>”;
echo ‘aaaaa’;
*/
$num = 0;
$arr = new arrayobject();
$arr = array();
$emap = bsGetEmaplist($userId, -1, $arr, $num );
var_dump($emap);
echo “<br/>”;
//var_dump($arr);
print_r($arr);
echo “<br/>”;
var_dump($num);
四、 输出结果
[root@localhost php]# php demo.php
PHP Notice: Undefined variable: userId in /root/php/demo.php on line 20
111111
222222
0 1 emapname_0
1 2 emapname_1
2 3 emapname_2
3 4 emapname_3
4 5 emapname_4
bool(true)
<br/>Array
(
[0] => stdClass Object
(
[ID] => 0
[pID] => 1
[name] => emapname_0
)
[1] => stdClass Object
(
[ID] => 1
[pID] => 2
[name] => emapname_1
)
[2] => stdClass Object
(
[ID] => 2
[pID] => 3
[name] => emapname_2
)
[3] => stdClass Object
(
[ID] => 3
[pID] => 4
[name] => emapname_3
)
[4] => stdClass Object
(
[ID] => 4
[pID] => 5
[name] => emapname_4
)
)
<br/>int(0)