我有一个库,我使用 SWIG 创建了一个 python 包装器。该库本身接受用户提供的函数,这些函数位于动态链接的 .so 文件中。目前,我正在处理我自己创建的一个,并设法在 C++ 中使动态链接正常工作。当我尝试在 python 中运行它时,出现未定义的符号错误。这些符号不存在于提供的 .so 文件中,但存在于主程序中(本质上它们是允许提供的模块访问主程序中的数据的函数)。
我在 C++ 中运行一个简短的测试程序没有遇到任何错误,但是使用这个包装器(之前工作过)在 python 中运行一个简短的测试程序失败了。我想不出为什么它在 C++ 中失败而不是在 python 中失败的解释。让我稍微担心的是 C++ 无法正常工作但没有告诉我,并且 python 正在拾取 C++ 没有的错误。然而 C++ 返回的结果是准确的,所以这似乎不太可能。
有什么想法这是可能的,因此我该如何解决它?
Thanks.
更新:
我已将此代码添加到程序的顶部:
import dl
sys.setdlopenflags(dl.RTLD_NOW | dl.RTLD_GLOBAL)
这消除了运行时错误,但不幸的是导致第二个问题出现(仍然是由于链接)。从作为主程序一部分的动态链接库中调用的函数未返回正确的值。它们返回 0。更重要的是,很明显它们根本没有被运行。问题是实际运行的是什么,为什么它与 C++ 不同,以及如何解决这个问题?
再次感谢。
更新-可能更清晰的解释
Python 导入一个模块,这是我的 C++ 库,已被 SWIG 封装。此 C++ 库使用 dlopen 和 dlsym 从用户提供的 .so 文件中获取函数。用户提供了对 C++ 库中的函数的文件调用来完成其工作。从 .so 文件到 C++ 库的函数调用是失败的部分,即它们无法调用该函数,只是返回 0。但是,只有当测试代码是用 python 编写时,才会出现这种失败。使用该库的 C++ 测试代码运行良好。
解决方案是确保 python 在全局范围内预加载 C++ 主库。
这不是一个非常优雅的解决方案,我也不想这样做,但它暂时可以工作。
经过一番探索后here http://linux.die.net/man/8/ld-linux并认识到每次启动终端时都必须设置的 LD_LIBRARY_PATH 环境变量,以便它找到已 SWIGed 的主 C++ 库,我注意到 LD_PRELOAD 环境变量。将其设置为主 C++ 库的文件名后,程序即可运行。
我怀疑这是因为它“可以用来选择性地覆盖其他共享库中的函数”。
如果有人想出比设置环境变量更好的答案,那就太棒了,因为我不确定它的可移植性如何。
编辑:最初的问题是用户提供的库正在寻找的函数不在全局范围内。为了解决这个问题,只需使用 python 的“dl.open”打开主库的 .so 文件,使用 dl.RTLD_NOW 和 dl.RTLD_GLOBAL。
Success!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)