简体   繁体   English

Boost 不静态链接到 boost::python 共享对象

[英]Boost not statically linking in to boost::python shared object

I've created a wrapper for my application using boost::python.我已经使用 boost::python 为我的应用程序创建了一个包装器。

This has worked so far by: (number of static libraries/source code) -> python_mapping.so到目前为止,这是有效的:(静态库/源代码的数量)-> python_mapping.so

In this way my shared object is comprised of many static libs, including boost itself (notably boost_thread).通过这种方式,我的共享对象由许多静态库组成,包括 boost 本身(特别是 boost_thread)。 I would assume that this so would contain ALL my application information, as I've statically linked everything in.我认为这将包含我所有的应用程序信息,因为我已经静态链接了所有内容。

This compiles just fine.这编译得很好。

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)

However, when I run my example python application I get this run time linking error: undefined symbol: _ZTIN5boost6detail16thread_data_baseE但是,当我运行我的示例 python 应用程序时,我得到这个运行时链接错误:未定义符号:_ZTIN5boost6detail16thread_data_baseE

It seems that those boost libraries that linked in fine to the static library aren't actually there?似乎那些很好地链接到静态库的 boost 库实际上并不存在?

I made some progress on this.我在这方面取得了一些进展。 Apparently my shared object doesn't include a lot of symbols the compiler didn't think were being used (because it never saw my c++ objects ever being created, since the are created by instantiating Python Objects).显然,我的共享对象不包含很多编译器认为没有被使用的符号(因为它从未见过我的 c++ 对象被创建,因为它们是通过实例化 Python 对象创建的)。

Kind of like:有一些像:

//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

Compiler will optimize out the CPlusCPlus class out because it never sees it actually being used, which is totally obnoxious.编译器将优化 CPlusCPlus 类,因为它从未看到它实际被使用,这完全令人讨厌。 It does seem to keep the PythonClass itself (probably because of the Python Boost Mapping Macro.它似乎确实保留了 PythonClass 本身(可能是因为 Python Boost 映射宏。

You can get around that a few ways:你可以通过几种方式解决这个问题:

  1. Link all your libraries with: -Xlinker --whole-archive使用以下链接链接所有库: -Xlinker --whole-archive
  2. Create dummy uses of the libraries in your shared object在共享对象中创建库的虚拟使用

I was wondering if anyone can think of another solution, because it is really annoying to go through all the possible libraries and add them in with --whole-archive .我想知道是否有人能想到另一种解决方案,因为浏览所有可能的库并将它们添加到 --whole-archive 中真的很烦人。

OK, since no one has responded, I've found the easiest (and only solution I know of) is to include EVERY static library you have as:好的,由于没有人回应,我发现最简单的(也是我所知道的唯一解决方案)是包含您拥有的每个静态库:

-Xlinker --whole-archive

You can, of course, link your libraries dynamically, which will require you to set LD_LIBRARY_PATH when executing your python application (though this wasn't an option for me for many libraries).当然,您可以动态链接您的库,这将要求您在执行 Python 应用程序时设置 LD_LIBRARY_PATH(尽管对于许多库来说这不是我的选择)。

So, in this sense, explicit dynamic linking might be considered a more elegant solution.因此,从这个意义上说,显式动态链接可能被认为是更优雅的解决方案。

Beyond that, if your libraries use other libraries:除此之外,如果您的库使用其他库:

python_mapping.so -> static linked in utility1.a -> static linked in utility2.a python_mapping.so -> 在utility1.a 中静态链接 -> 在utility2.a 中静态链接

If you've forgotten to link in utility1.a running the python application will let you know it can't find the symbols, however, it will NOT complain about utility2.a, and will have weird behavior when it reaches that part of the library.如果您忘记在utility1.a中链接,运行python应用程序会让您知道它找不到符号,但是,它不会抱怨utility2.a,并且当它到达该部分时会出现奇怪的行为图书馆。 So... be careful and make sure you've explicitly linked in EVERYTHING.所以......小心并确保你已经明确地链接到一切。

You can use the linker parameter -rpath to embed a library search path, including "current directory" in your executable (g++ -Wl,-rpath,.) so you can specify exactly from where to load the shared libraries.您可以使用链接器参数 -rpath 在可执行文件中嵌入库搜索路径,包括“当前目录”(g++ -Wl,-rpath,.),以便您可以准确指定从何处加载共享库。 This helps if you are moving your application around to other machines whose .so files are unknown.如果您将应用程序移动到其他 .so 文件未知的机器上,这会有所帮助。 You'd have to also move over the .so files you explicitly specified.您还必须移动您明确指定的 .so 文件。 It's a compromise between static linking, and full dynamic linking because you won't actually be "sharing" the .so file with other apps on the box (you brought your own copies over), one of the memory saving benefits of using shared libraries.这是静态链接和完全动态链接之间的折衷,因为您实际上不会与包装盒上的其他应用程序“共享” .so 文件(您带来了自己的副本),这是使用共享库节省内存的好处之一.

This post is mostly to publicize the rarely used, but very useful -rpath parameter.这篇文章主要是为了宣传很少使用但非常有用的 -rpath 参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM