php第三方函数库,PHP拓展开发 - 在扩展里调第三方函数

如何调用php标准库的函数

实战场景:想写一个简单的获取token的函数。token由任意前缀+随机数组成。

重点:随机数部分联想到了php有实现了,可直接调用。

1、引入php标准库头文件

搜索rand函数定义的文件:

grep -rn "PHP_FUNCTION(RAND)" ./ext

找到在/ext/standard/rand.c里头。我们要找的是头文件,故进一份分析,rand函数主要核心方法是调用了php_rand函数,发现原来是需要引入:

#include "php_rand.h"

是不是这个头文件里头声明的函数都可以调用呢?

答案是no,只能调用php_rand.h 头文件声明的PHPAPI的函数。

2、使用标准库的函数

如果不知道怎么使用可以这么分析:在PHP_FUNCTION(rand)函数中,找到调用的例子:

PHP_FUNCTION(rand)

{

long min;

long max;

long number;

int argc = ZEND_NUM_ARGS();

if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE)

return;

number = php_rand(TSRMLS_C);//TSRMLS_C代表线程安全,此处可直接使用,用的时候照着那个传就行。如果参数是别的,需要找参数的来源,在源文件中搜索或者参数是php调用的时候传的,找到参数的意义,就好了。

if (argc == 2) {

RAND_RANGE(number, min, max, PHP_RAND_MAX);

}

RETURN_LONG(number);

}

可以发现关键的实现代码是:

number = php_rand(TSRMLS_C);

RAND_RANGE(number, min, max, PHP_RAND_MAX);

好了,调用技能get到了

3、函数的实现

需要先添加PHP_FE(get_token, NULL) 注册函数,后实现函数。

PHP_FUNCTION(get_token) {

// 1.定义参数

long min = 1;

long max = 100;

char *prefix;

int prefix_len;

long number;

char sz[10];

// 2.接收token的前缀

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &prefix, &prefix_len) == FAILURE) {

return;

}

// 3.获取随机数

number = php_rand(TSRMLS_C);

RAND_RANGE(number, min, max, PHP_RAND_MAX);

// 4.随机数转成字符串,方便拼接,否则会报make时候会有错误提示。

sprintf(sz, "%d", number);

// 5.拼接前缀与随机数

strcat(prefix, sz);

// 6.返回结果

RETURN_STRING(prefix, 1);

}

重新走一波编译安装流程(phpize && make && make install && /etc/init.d/php-fpm restart)

测试:

$token = get_token('test');

echo $token;

至此,调用php标准库done。

如何调用php原生的函数

实战场景:还是想写一个简单的获取token的函数。token由任意前缀+随机数组成。

重点:随机数部分用php原生的函数mt_rand实现。那么c扩展怎么调用原生的php函数呢?

1、详解重点方法call_user_function

官方的定义:

ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC);

ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, zend_uint param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC);

竟然有两个函数,通过查看源码./Zend/zend_execute_API.c

是的,call_user_function封装了call_user_function_ex,直接使用call_user_function就好了。

参数讲解:

5b68036b4360

2、函数的实现

需要先添加PHP_FE(get_token_b, NULL) 注册函数.

//定义一个将整形转成zval型的函数(在查询鸟哥怎么用call_user_function的时候,发现的函数,原先是字符串变zval型,给稍微改了下整形变zval型)

static zval *_change_long_zval(long num)

{

zval *ret;

MAKE_STD_ZVAL(ret);

if (num) {

ZVAL_LONG(ret, num);

} else {

ZVAL_NULL(ret);

}

return ret;

}

PHP_FUNCTION(get_token_b) {

long min; // 随机数最小值

long max; // 随机数最大值

char *prefix; // 前缀

int prefix_len; // 前缀长度

char sz[10]; // 长整型转字符串时候用到

zval *func_name; // 函数名字

zval *retval; // 返回值

zval *params[1]; // 装参数的数组

// 获取参数

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &prefix, &prefix_len, &min, &max) == FAILURE) {

return;

}

// 申请一个内存

MAKE_STD_ZVAL(func_name);

// 赋值要调用的函数

ZVAL_STRING(func_name,"mt_rand", 1);

// 设置参数

params[0] = _change_long_zval(min);

params[1] = _change_long_zval(max);

// 申请返回值的内存空间

MAKE_STD_ZVAL(retval);

// 调用函数

if(call_user_function(CG(function_table),NULL,func_name,retval,2,params TSRMLS_DC)==FAILURE){

return;

}

// 转字符串

sprintf(sz, "%d", Z_LVAL_P(retval));

// 拼接返回结果

strcat(prefix, sz);

RETURN_STRING(prefix, 1);

}

测试:

$token = get_token_b('test',1,1000);

echo $token;

调用php原生函数done。

如何调用php写的函数

实战场景:还是想写一个简单的获取token的函数。token由任意前缀+随机数组成。

重点:随机数部分用我们自己写的php函数来实现。那么c扩展怎么调用自己写的php函数呢?

1、重点函数

当然还是call_user_function

2、函数的实现

需要先添加PHP_FE(get_token_c, NULL) 注册函数.

PHP_FUNCTION(get_token_c) {

zval *func_name;

zval *args;

zval *retval;

zval *params[1];

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &func_name, &args) == FAILURE) {

return;

}

if (Z_TYPE_P(func_name) != IS_STRING){

return;

}

params[0] = args;

MAKE_STD_ZVAL(retval);

if(call_user_function(CG(function_table),NULL,func_name,retval,1,params TSRMLS_DC)==FAILURE){

return;

}

RETURN_STRING(Z_STRVAL_P(retval),1);

}

测试:

function get_token_demo($prefix){

return "token :".$prefix.mt_rand(1,1000);

}

echo get_token_c("get_token_demo","test");

至此,三种调用都已经

以上

欢迎大家关注我的公众号

5b68036b4360

半亩房顶

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值