【问题标题】:custom PHP extension自定义 PHP 扩展
【发布时间】:2014-09-16 10:48:36
【问题描述】:

我需要为 PHP 创建自定义扩展。一切都很顺利,直到我想将编译的扩展加载到 PHP 中。比我收到此错误消息(通过使用 php -m):“警告:PHP 启动:无效库(可能不是 PHP 库)'first.so' in Unknown on line 0”

操作系统:

OS X 10.8.5

这是我的编译过程,完全没有错误:

$ phpize54
$ sudo ./configure --with-php-config=/opt/local/bin/php-config54
$ sudo make install

我正在通过 .ini 文件在 dir 中为其他 .ini 文件注册扩展名

extension=first.so

我没有使用其他其他工具。当我试图以这种方式从 PHP 分发源(具体来说是posix)中包含的扩展中编译一些扩展时,一切正常并且扩展被正确加载。

有人在下面的源代码中看到任何错误吗?谢谢你的帮助。

config.m4

PHP_ARG_ENABLE(first,whether to enable FIRST functions,
[  --disable-first         Disable FIRST functions], yes)

if test "$PHP_FIRST" = "yes"; then
  AC_DEFINE(HAVE_FIRST, 1, [whether to include FIRST functions])
  PHP_NEW_EXTENSION(first, first.c, $ext_shared)
fi

first.c

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "ext/standard/info.h"

extern zend_module_entry first_module_entry;
#define first_module_ptr &first_module_entry
#define phpext_first_ptr first_module_ptr


static PHP_MINFO_FUNCTION(first)
{
    php_info_print_table_start();
    php_info_print_table_row(2, "Revision", "$Id: 01 $");
    php_info_print_table_end();
}

static PHP_MINIT_FUNCTION(first)
{
    return SUCCESS;
}

PHP_FUNCTION(hallo)
{
    RETURN_STRING("FIRST extension function works\n", 1);
}

ZEND_BEGIN_ARG_INFO_EX(arginfo_hallo, 0, 0, 0)
ZEND_END_ARG_INFO()

const zend_function_entry first_functions[] =
{
    PHP_FE(hallo, arginfo_hallo)
    PHP_FE_END
};

zend_module_entry first_module_entry = {
    STANDARD_MODULE_HEADER,
    "first", 
    first_functions, 
    PHP_MINIT(first),
    NULL,
    NULL,
    NULL, 
    PHP_MINFO(first),
    NO_VERSION_YET,
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_POSIX
ZEND_GET_MODULE(first)
#endif

【问题讨论】:

  • 你是如何生成共享库的?
  • 复制这个问题需要更多细节:你是如何编译代码的?你是如何注册扩展的?您正在使用什么工具(即 ext_skel 或其他工具),您遇到了什么错误(除了您在问题中包含的错误)?
  • OS: OS X 10.8.5 这是我的编译过程,完全没有错误: $ phpize54 $ sudo ./configure --with-php-config=/opt/local/bin /php-config54 $ sudo make install 我正在通过 .ini 文件在 dir 中注册扩展以获取其他 .ini 文件 extension=first.so 我没有使用其他其他工具。当我试图以这种方式从 PHP 分发源(具体来说是posix)中包含的扩展中编译一些扩展时,一切正常并且扩展被正确加载。
  • 您不应该使用 sudo 进行配置或编译,您只需要 root 权限才能在 root 文件系统中安装文件(使用 make install)。对于测试,您不需要在 make 之后 make install either, but can use a relative path (i.e. php -dextension=modules/foo.so`)。如果构建系统中存在错误或其他问题,使用 sudo 可能会产生不良后果,并且由于突然工作目录中的文件由需要更多 sudo 的 root 拥有,这也很烦人,从而增加了发生事故的机会。

标签: php c compiler-errors extension-methods


【解决方案1】:
#ifdef COMPILE_DL_POSIX
ZEND_GET_MODULE(first)
#endif

这看起来不对。在 config.m4 中,您声称首先调用了您的扩展程序 (PHP_NEW_EXTENSION(first, ...),但是您正在检查是否构建了名为 posix 的扩展程序共享。

背景:PHP 可以通过两种方式加载扩展(意味着 PHP 模块 与 Zend 扩展如 xdebug 或 opcache 相混淆 - 它们是不同的主题)。静态编译成 PHP 或共享。

静态意味着您的扩展是作为 PHP 的一部分构建的,并且直接构建在 php 二进制文件中。 (将它放在 php-src/ext/ 中,运行 buildconf,配置)这通过配置创建一个包含所有 php_foo.h 文件的文件 main/internal_functions.c 并创建一个在 PHP 启动时处理的 module_entry 数组来工作。

如果扩展是构建共享的(在 php-src 或 phpize 中使用 --with-foo=shared)并通过 php.ini 加载它,PHP 将使用 dlopen()dlsym() 系统 API 查找函数 get_module()(或 LoadDll 在 Windows 上)将返回模块结构。为了避免一直编写函数get_module(),宏ZEND_GET_MODULE 会这样做。但是get_module 是一个通用名称,并且在静态构建期间必须防止每个扩展创建它,因为这会导致冲突在同一个二进制文件中多次具有相同的功能,这就是构建系统创建 COMPILED_DL_FOO 定义的原因可以用作守卫。

因此,在您的情况下,PHP 会打开库,查找 get_module() 但找不到,耸耸肩并报告错误。

参考资料:

【讨论】:

    猜你喜欢
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多