【问题标题】:PHP Extension: Defined function is undefinedPHP 扩展:定义的函数未定义
【发布时间】:2012-08-29 20:19:26
【问题描述】:

我正在为我的 Raspberry Pi 创建一个 SPI 扩展,并且在我尝试添加的类函数中遇到了一个相当奇怪的问题。 (如果你想检查我遗漏的任何明显的东西,repo 就在这里:php_spi on Github

在我的 php_spi.h 中我定义了:

PHP_METHOD(Spi, blockTransfer);
#if (PHP_MAJOR_VERSION >= 5)
ZEND_BEGIN_ARG_INFO_EX(Spi__blockTransfer_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
#if (PHP_MINOR_VERSION > 0)
  ZEND_ARG_ARRAY_INFO(0, data, 1)
#else
  ZEND_ARG_INFO(0, data)
#endif
  ZEND_ARG_INFO(0, colDelay)
  ZEND_ARG_INFO(0, discard)
ZEND_END_ARG_INFO()
#else /* PHP 4.x */
#define Spi__blockTransfer_args NULL
#endif

这与其他一些方法一起,类似地定义了当前有效的方法。在我的 spi.c 文件中,函数定义如下:

    /* {{{ proto array blockTransfer(array data[, int colDelay[, bool discard]])
   */
PHP_METHOD(Spi, blockTransfer)
{
    zend_class_entry * _this_ce;

    zval * _this_zval = NULL;
    zval * data = NULL;
    HashTable * data_hash = NULL;
    long colDelay = 1;
    zend_bool discard = 0;

    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "a|lb", &_this_zval, Spi_ce_ptr, &data, &colDelay, &discard) == FAILURE) {
        return;
    }

    _this_ce = Z_OBJCE_P(_this_zval);

    // some code
}
/* }}} blockTransfer */

并且我已经确保我的函数在函数列表中有一个条目:

static zend_function_entry Spi_methods[] = {
    PHP_ME(Spi, __construct, Spi____construct_args, /**/ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
    PHP_ME(Spi, __destruct, Spi____destruct_args, /**/ZEND_ACC_PUBLIC | ZEND_ACC_DTOR)
    PHP_ME(Spi, transfer, Spi__transfer_args, /**/ZEND_ACC_PUBLIC)
    PHP_ME(Spi, blockTransfer, Spi__blockTransfer_args, /**/ZEND_ACC_PUBLIC)
    PHP_ME(Spi, getInfo, Spi__getInfo_args, /**/ZEND_ACC_PUBLIC)
    PHP_ME(Spi, setupTimer, Spi__setupTimer_args, /**/ZEND_ACC_PUBLIC)
    PHP_ME(Spi, usecDelay, Spi__usecDelay_args, /**/ZEND_ACC_PUBLIC)
    { NULL, NULL, NULL }
};

代码编译干净,没有错误或警告,但是当我尝试测试该函数时,我收到一个 PHP 错误,指出该函数未定义。我可能会错过什么?

(为了清楚起见,这是一个工作扩展,除了这个功能)

编辑:感谢您对超过一年的问题投反对票。

【问题讨论】:

  • 我过去做过的一件愚蠢的事情是忘记在 ZEND_GET_MODULE() 语句周围定义常量。
  • 我确信 - 我的扩展程序的所有其他部分都按预期工作。
  • 也许这很傻,但是你用什么编译器来编译你的 spi.c?如果这是 g++,它可能会将类型信息添加到导出的函数中。还是你使用 gcc(如果你使用 unix/linux...)
  • @Grzegorz 但是为什么它只对一个函数这样做 - 我的类中的其余方法加载得很好

标签: php c php-extension


【解决方案1】:

首先要检查的是 PHP 是否找到了模块 - 尝试在命令行上运行 php -m 或在网页中调用 phpinfo() - 是否列出了您的模块?

如果没有,请查看How to enable php extension using `phpize`? 另外,您的环境是什么?

【讨论】:

  • PHP 正在查找 Spi 类实例化的模块,我可以运行我定义的所有其他方法,只是这个函数不想工作。我的环境是 Raspbian(基于 Debian Wheezy,为 ARM 编译),运行在树莓派上
  • @frak 你解决了吗?我刚刚检查了您的 Git 存储库,并没有提到 blockTransfer 方法。但是,如果我复制问题中的代码,它就可以正常工作...
  • 如果你有 master 签出,你将看不到代码,如果你尝试签出块发送分支,你应该会看到代码。奇怪的是它似乎对你有用:S
【解决方案2】:

您定义了数组Spi_methods,但没有引用它。必须在模块结构中引用;例如见this example

您不需要将函数或 arginfo 原型放在主扩展头(或任何其他头,除非您需要在其他编译单元中引用符号,例如,如果您在一个文件中定义了一个函数,但在另一个中构建函数入口数组)。事实上,我认为它会自动包含在静态构建中,所以你不应该为了避免名称冲突。

【讨论】:

  • 我已经有了这个,如果没有它,其他所有方法都如何工作?原型定义来自 PECL_CodeGen,所以我想我不妨继续约定,并且它不会对我拥有的任何其他方法造成任何问题,效果很好
【解决方案3】:

嗯,在我的测试文件中的错字上浪费了很多时间:o(

我应该更仔细地阅读错误,因为它是关于函数 blockTransfer() 未定义,而不是方法。

在我的测试文件中:

$read = $spi-blockTransfer();

哇!

很抱歉浪费了您的时间。

【讨论】:

    猜你喜欢
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-07
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    相关资源
    最近更新 更多