PHP 扩展返回结构

问题描述 投票:0回答:1

我正在开发一个 PHP 扩展,想让 PHP 返回一个结构。但它总是会导致核心转储。我的步骤是:

  1. ./ext_skel --extname=test

  2. ./configure --enable-test

  3. php_test.h
    中添加:

     typedef struct  mydata {
         int   m_id;
         int   m_age;
     }MYDATA;
     PHP_FUNCTION(wrap_getMydata);`
    
  4. 在test.c中添加:

     #define MY_RES_NAME "my_resource";
     static int my_resource_descriptor;
     PHP_FE(wrap_getMydata, NULL)
     ...
     ZEND_MINIT_FUNCTION(test)
     {
         /* If you have INI entries, uncomment these lines
         REGISTER_INI_ENTRIES();
         */
         resid = zend_register_list_destructors_ex(NULL, NULL, MY_RES_NAME, module_number);
    
         return SUCCESS;
     }
    
     PHP_FUNCTION(test_getMydata)
    
     {
         zval* res;
         long int a, b;
         long int result;
    
         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) {
             return;
         }
         MYDATA objData;
         objData.m_id = a;
         objData.m_age = b;
         ZEND_REGISTER_RESOURCE(res, &objData, resid);
         RETURN_RESOURCE(res);
     }
    
  5. 添加:

    var_dump(test_getMydata(3,4))
    test.php

  6. 然后

    make; make install; ./php test.php
    ,它打印:

     Functions available in the test extension:
     confirm_wrap_compiled
     test_getMydata
     Congratulations! You have successfully modified ext/wrap/config.m4. Module wrap is now compiled into PHP.
     Segmentation fault (core dumped)
    
  7. $ gdb ../../bin/php core.23310

     Loaded symbols for /home/user1/php/php-5.2.17/lib/php/extensions/no-debug-non-zts-20060613/test.so 
     #0  0x00000000006388ad in execute (op_array=0x2a9569bd68) at /home/user1/php/php-5.2.17/Zend/zend_vm_execute.h:92
     92                      if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0) {`
    

问题产生的原因是什么以及如何解决?

php php-extension
1个回答
0
投票

我必须将扩展名从

test
重命名为
hjtest
- 其他所有内容都应该与您发布的示例非常一致。

tl;dr - 问题 - 和样本中的

SIGSEGV
是您正在将资源注册到局部变量
objData
- 在函数末尾不再可达 - 您需要使用
emalloc
来获取一块动态内存 - 保存您的
MYDATA

从那里开始,你就有了一个资源 - 绑定到某些 dyn 上。内存,您需要注册一个 dtor 函数 - 这样您就可以释放/

efree
您注册的内存。

要解决上述问题 - 修改您的资源注册,如下所示:

    MYDATA * objData=emalloc(sizeof(MYDATA));
    objData->m_id = a;
    objData->m_age = b;
    ZEND_REGISTER_RESOURCE(return_value, objData, resid);

并添加一个 dtor: ...迷你

 resid = zend_register_list_destructors_ex(resdtor, NULL, MY_RES_NAME, module_number);

static void resdtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
    {
        MYDATA *res = (MYDATA*)rsrc->ptr;
        if (res) {
          efree(res);
        }
    }

有关完整示例,请参阅此 GIST:https://gist.github.com/hjanuschka/3ed54e66f017a379cf25

© www.soinside.com 2019 - 2024. All rights reserved.