构建 PHP 扩展时如何检查未损坏的 C++ 符号?

Posted

技术标签:

【中文标题】构建 PHP 扩展时如何检查未损坏的 C++ 符号?【英文标题】:How do I check for an unmangled C++ symbol when building a PHP extension? 【发布时间】:2009-04-28 15:15:40 【问题描述】:

我有一个用 C++ 编写的 php 模块,它依赖于安装的 C++ 库 (Boost Date_Time)。

目前,在我的 config.m4 文件中,我正在检查库,如下所示:

  LIBNAME=boost_date_time
  LIBSYMBOL=_ZN5boost9gregorian9bad_monthD0Ev

  PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,,
  [
    AC_MSG_ERROR([lib $LIBNAME not found.  Try: sudo apt-get install libboost-dev])
  ],[
    -lstdc++ -ldl
  ])

现在,这适用于我当前的环境,但我很痛苦地意识到这可能会在不同版本的库或编译器上中断。

如何让 automake 理解未损坏的 C++ 符号?

编辑:

我意识到检查损坏的名称是可怕的,但是没有某种方法可以检查“nm -C”返回的符号名称(例如 boost::gregorian::bad_month 等)。

我找到了一些对 automake 命令 AC_LANG_CPLUSPLUS() 的参考,但我不确定如何使用它以及它是否适用于此。

【问题讨论】:

【参考方案1】:

你可以用类似的方式检查AC_TRY_COMPILE

LIBNAME=boost_date_time
AC_MSG_CHECKING([for BOOST])
AC_TRY_COMPILE(
[
#include "boost/date_time/gregorian/greg_month.hpp"
],
[
boost::gregorian::bad_month* bm = new boost::gregorian::bad_month;
],
[
AC_MSG_RESULT(yes)
],
[
AC_MSG_ERROR([lib $LIBNAME not found.  Try: sudo apt-get install libboost-dev])
])

这避免了使用未损坏的符号。

【讨论】:

【参考方案2】:

在特定 C++ 编译器的环境之外,没有“未损坏的 C++ 符号” - 损坏的目的是为外部工具(例如链接器和库管理器)提供唯一的名称。

【讨论】:

【参考方案3】:

这是一个糟糕的主意——公开损坏的符号。你为什么首先需要这个?

看到您的更新后,我不得不问,为什么不使用自定义规则来调用 nm 并获取此信息并将此规则作为要求传递?如果autoconf 提供直接命令来检查目标文件中的符号,我会感到非常惊讶。

【讨论】:

我可以理解他的动机 - 损坏的名称将在库中或不在库中,如果不存在则表示错误。他实际上并没有尝试调用已损坏(或未损坏,在此上下文中)的函数。 添加自定义规则不是一个坏主意。请注意,该命令的 PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,, 等部分正是如此 - 一个 PHP 特定的宏,用于检查目标文件中的符号。但当然只适用于 C 符号。【参考方案4】:

您需要为您希望调用的 Boost api 函数提供一组 C++ 包装器。这些包装器需要用extern "C" 声明,如:

extern "C" 
void foo(int bar) 

...

您的 PHP 代码应该使用这些包装器,而不是尝试直接调用 C++ 方法。

编辑:由于您假设automake 的可用性,您可能计划编译Boost 库作为安装的一部分。这使您可以选择探测名称修改的结果。尝试按照这些思路创建一个测试 C++ 程序。 注意这里只需要编译;它不需要产生有效的结果。

#include "boost/date_time/gregorian/greg_month.hpp"
int main( int argc, const char* argv[] )

   boost::gregorian::bad_month* xxxjunk = new boost::gregorian::bad_month;
   return 0;

在您的 automake 中,您需要编译它,然后通过

运行输出
nm -C | grep "boost::gregorian::bad_month"

根据您的需要和挑剔,您可能希望进一步细化 grep 命令以查找字符串“typeinfo for boost::gregorian::bad_month”(请注意,这会进一步增加您对特定编译器实现的依赖。)

【讨论】:

以上是关于构建 PHP 扩展时如何检查未损坏的 C++ 符号?的主要内容,如果未能解决你的问题,请参考以下文章

使用 numpy 和 gdal 的 Python C 扩展在运行时给出未定义的符号

VC DLL 中 C++ 符号的 MinGw 未定义符号

c++ 运行时检查失败 #2 - 变量“ToSend22”周围的堆栈已损坏

LNK2019“未解析的外部符号”错误(C++ OpenGL)

与静态库中的 std::string 相关的 C++ 未定义符号

PHP:如何检查 gz 文件是不是损坏?