构建 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 扩展在运行时给出未定义的符号
c++ 运行时检查失败 #2 - 变量“ToSend22”周围的堆栈已损坏
LNK2019“未解析的外部符号”错误(C++ OpenGL)