在PHP扩展中通过C语言调用PHP函数与方法

在扩展中调用PHP函数是一件很繁琐的事情,这里给大家带来一个现成的函数,可以极大的方便大家在扩展中调用php函数与方法。
函数原型:int walu_call_user_function(zval** retval, zval* obj, char* function_name, char* paras, …);
调用成功返回1,失败返回0.
各个参数的说明:
retval,zval**类型的,代表返回值。如果你需要返回值,请传递一个zval**类型的变量,不需要返回值可以传递NULL。
obj,对象实例对应的zval*,如果是PHP函数此处传递NULL。
function_name,字符串,内容为函数或者方法的名称。
paras,字符串,由一系列转换字符组成,转换字符由:s,b,z,n组成。
其它参数,根据paras里的转换字符,给出具体的数据,每个转换字符对应的数据如下:

    s  :  char* str, int len。
    b  :  int bool, 1代表true,0代表false。
    n  :  代表NULL,它不需要提供数据。
    z  :  zval *val, 一般是对象、数组、资源。
    d  : double num;

调用时候需要注意的几点:

    对于z型参数,调用过程中walu_call_user_function本身不会修改、释放它。
    对于参数中的retval,如果不是NULL,调用者使用完成后不要忘记zval_ptr_dtor(retval一下);


下面准备了几个实例,来解释它的用法。

实例一:调用explode函数,参数为”,”与“1,3,4”;
//调用函数测试:zval *val;walu_call_user_function(&val, NULL, "explode", "ss", ",", 1, "1,3,4", sizeof("1,3,4")-1);php_var_dump(&val); //看下函数调用的结果是多少啊~~zval_ptr_dtor(&val);//千万不要忘了这一步

输出为:
array(3) { [0]=> string(1) "1" [1]=> string(1) "2" [2]=> string(1) "3"}
实例二:调用对象$obj的print_arg方法。
假设有这么一个类:
class demo{    public function print_arg()    {
         $args = func_get_args();
         var_dump($args);
   }}

test_call是扩展提供的一个函数,我们通过此函数接收$obj,然后调用它的args方法。
zval* obj;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &obj) == -1){   
     php_printf("Wrong!\n");
     return;
}//这次尝试一下不是用返回值。
walu_call_user_function(NULL, obj, "print_arg", "snbbd", "hello", sizeof("hello")-1, 1, 0, 1.29292);

输出为:
array(5) {  [0]=>  string(5) "hello"  [1]=>  NULL  [2]=>  bool(true)  [3]=>  bool(false)  [4]=>  float(1.29292)}源码:
#include "php.h"#include "php_ini.h"#include "ext/standard/info.h"#include "Zend/zend_list.h"#include "Zend/zend_interfaces.h" int walu_call_user_method(zval** retval, zval* obj, char* function_name, char* paras, ...){        //用于接收参数
       short int paras_count=0;
        zval*** parameters = NULL;
         long long_tmp;
       char *string_tmp;
       zval *zval_tmp;
       double dou_tmp;
       int i;         //仅与调用有关的变量
      int fun_re, retval_is_null=0;
       HashTable *function_table;         //接收参数
       paras_count = strlen(paras);
       if(paras_count > 0)        {
                parameters = (zval***)emalloc(sizeof(zval**) * paras_count);
                va_list ap;
                va_start(ap,paras);
                for(i=0; i<paras_count; i++)                {
                        parameters[i = (zval**)emalloc(sizeof(zval*));
                         switch(paras[i)                        {
                                case 's':
                                       MAKE_STD_ZVAL(*parameters[i);
                                       string_tmp = va_arg(ap, char*);
                                       long_tmp = va_arg(ap, long);  
                                      ZVAL_STRINGL(*parameters[i, string_tmp, long_tmp, 1);
                                        break;
                                case 'l':  
                                       MAKE_STD_ZVAL(*parameters[i);
                                        long_tmp = va_arg(ap, long);
                                        ZVAL_LONG(*parameters[i, long_tmp);  
                                       break;                                 case 'd':  
                                       MAKE_STD_ZVAL(*parameters[i);
                                        dou_tmp = va_arg(ap, double);
                                        ZVAL_DOUBLE(*parameters[i, dou_tmp);
                                        break;
                                case 'n':
                                       MAKE_STD_ZVAL(*parameters[i);
                                       ZVAL_NULL(*parameters[i);
                                       break;
                                 case 'z':
                                       zval_tmp = va_arg(ap, zval*);
                                       *parameters[i = zval_tmp;
                                        break;
                                 case 'b':  
                                      MAKE_STD_ZVAL(*parameters[i);  
                                      ZVAL_BOOL(*parameters[i, (int)va_arg(ap, int));
                                        break;
                               default:
                                        zend_error(E_ERROR, "Unsupported type:%c in walu_call_user_function", paras[i);                                        return 0;
                        }
               }
                 va_end(ap);
        }         //构造参数执行call_user_function_ex  
      zval *_function_name;
        MAKE_STD_ZVAL(_function_name);
        ZVAL_STRINGL(_function_name, function_name, strlen(function_name), 1);
          if(retval == NULL)        {
                retval_is_null = 1;
               retval = (zval**)emalloc(sizeof(zval*));
        }         //开始函数调用
       if(obj)        {
               function_table = &Z_OBJCE_P(obj)->function_table;
        }        else        {
                function_table = (CG(function_table));
        }
         zend_fcall_info fci;
        fci.size = sizeof(fci);
        fci.function_table = function_table;
        fci.object_ptr = obj ? obj : NULL;
        fci.function_name = _function_name;
       fci.retval_ptr_ptr = retval;
       fci.param_count = paras_count;
        fci.params = parameters;
        fci.no_separation = 1;
        fci.symbol_table = NULL;
       fun_re = zend_call_function(&fci, NULL TSRMLS_CC);         //函数调用结束。
        if(retval_is_null == 1)        {
               zval_ptr_dtor(retval);
                efree(retval);
        }
         zval_ptr_dtor(&_function_name);         //free掉parameter及其里面的每个元素zval**,及每个元素zval**对应的zval*        //对于传进来的zval,不进行free,由参数调用者自行free
       if(paras_count > 0)        {
               for(i=0; i<paras_count; i++)                {
                        if(paras[i != 'z')                        {
                                zval_ptr_dtor(parameters[i);
                        }
                        efree(parameters[i);
                }
                efree(parameters);
        }
       return fun_re;
}
来源:walu的破笔头
转载地址:http://www.yezis.cn/thread-299-1-1.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值