3

我使用 boost::python 为我的应用程序创建了一个包装器。

到目前为止,这已经通过:(静态库/源代码的数量)-> python_mapping.so

这样,我的共享对象由许多静态库组成,包括 boost 本身(特别是 boost_thread)。我会假设这将包含我所有的应用程序信息,因为我已经静态链接了所有内容。

这编译得很好。

ldd python_mapping.so
        librt.so.1 => /lib64/librt.so.1 (0x00002b7cbad37000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00002b7cbaf40000)
        libm.so.6 => /lib64/libm.so.6 (0x00002b7cbb240000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002b7cbb4c4000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00002b7cbb6d2000)
        libc.so.6 => /lib64/libc.so.6 (0x00002b7cbb8ed000)
        /lib64/ld-linux-x86-64.so.2 (0x000000327ee00000)

但是,当我运行我的示例 python 应用程序时,我得到这个运行时链接错误:未定义的符号:_ZTIN5boost6detail16thread_data_baseE

似乎那些链接到静态库的 boost 库实际上并不存在?

我在这方面取得了一些进展。显然,我的共享对象没有包含很多编译器认为没有被使用的符号(因为它从未见过我的 c++ 对象被创建,因为它们是通过实例化 Python 对象创建的)。

有一些像:

//This is a class only created in python
#include "CPlusPlusClass.h"

PythonClass
{
       public:
           PythonClass() { }
       private:
           CPlusPlusClass _cplusplus;
};

//PythonMappings for PythonClass

#python file
import python_mapping

pythonClass = python_mapping.PythonClass() #This fails saying it can't find the symbol for CPlusPlusClass

编译器将优化掉 CPlusCPlus 类,因为它从未看到它实际被使用,这完全令人讨厌。它似乎确实保留了 PythonClass 本身(可能是因为 Python Boost 映射宏。

您可以通过以下几种方式解决此问题:

  1. 将所有库链接到:-Xlinker --whole-archive
  2. 在共享对象中创建库的虚拟使用

我想知道是否有人能想到另一种解决方案,因为浏览所有可能的库并将它们添加到 --whole-archive 真的很烦人。

4

2 回答 2

2

好的,由于没有人回应,我发现最简单(也是我知道的唯一解决方案)是包含你拥有的每个静态库:

-Xlinker --whole-archive

当然,您可以动态链接您的库,这将要求您在执行 python 应用程序时设置 LD_LIBRARY_PATH(尽管对于许多库来说这不是我的选项)。

因此,从这个意义上说,显式动态链接可能被认为是一种更优雅的解决方案。

除此之外,如果您的库使用其他库:

python_mapping.so -> 在实用程序1.a 中静态链接 -> 在实用程序2.a 中静态链接

如果您忘记在运行 python 应用程序的实用程序1.a 中进行链接,它将让您知道它找不到符号,但是,它不会抱怨实用程序2.a,并且当它到达该部分时会出现奇怪的行为图书馆。所以...要小心,并确保您已明确链接到所有内容。

于 2012-09-28T22:33:22.073 回答
0

您可以使用链接器参数 -rpath 嵌入库搜索路径,包括可执行文件中的“当前目录” (g++ -Wl,-rpath,.),以便您可以准确指定从何处加载共享库。如果您将应用程序移动到 .so 文件未知的其他机器上,这将很有帮助。您还必须移动您明确指定的 .so 文件。这是静态链接和完全动态链接之间的折衷,因为您实际上不会与盒子上的其他应用程序“共享” .so 文件(您将自己的副本带过来),这是使用共享库的节省内存的好处之一.

这篇文章主要是为了宣传很少使用但非常有用的 -rpath 参数。

于 2013-06-21T16:07:57.133 回答