2

我有一个库,我使用 SWIG 创建了一个 python 包装器。库本身接受用户提供的函数,这些函数位于动态链接的 .so 文件中。目前,我正在处理我自己创建的一个,并设法让动态链接工作......在 C++ 中。当我尝试在 python 中运行它时,我得到未定义的符号错误。这些符号是提供的 .so 文件中不存在但存在于主程序中的符号(本质上它们是允许提供的模块从主程序访问数据的函数)。

在 C++ 中运行一个简短的测试程序时我没有遇到任何错误,但是在 python 中使用这个包装器(以前工作过)的一个简短的测试程序失败了。我想不出为什么它会在 C++ 中失败而不是在 python 中的解释。让我稍微担心的是 C++ 不能正常工作但没有告诉我的想法,并且 python 正在发现 C++ 没有的错误。然而 C++ 返回的结果是准确的,所以这似乎不太可能。

任何想法这是怎么可能的,因此我该如何解决它?

谢谢。

更新:我已将此代码添加到程序的顶部:

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++ 测试代码运行良好。

4

2 回答 2

2

一个解决方案是确保 python 在全局范围内预加载 C++ 主库。这不是一个非常优雅的解决方案,我不想这样做,但它让它暂时起作用。

在这里闲逛了一下并识别了每次启动终端时必须设置的 LD_LIBRARY_PATH 环境变量,以便它甚至可以找到已被 SWIGed 的主 C++ 库,我注意到 LD_PRELOAD 环境变量。将其设置为主 C++ 库的文件名后,程序就可以工作了。

我怀疑这是因为它“可以用来选择性地覆盖其他共享库中的函数”。

如果有人提出比设置环境变量更好的答案,那就太棒了,因为我不确定它的便携性。

编辑:最初的问题是用户提供的库正在寻找的功能不在全局范围内。为了解决这个问题,只需使用 python 的“dl.open”打开主库的 .so 文件,使用 dl.RTLD_NOW 和 dl.RTLD_GLOBAL。

成功!

于 2010-08-05T09:10:57.750 回答
1

python 解释器可能正在加载您的包装器 .so 而不使其符号可用于其他动态链接库(以避免符号冲突)。在导入包装器之前尝试添加以下行:

import dl
sys.setdlopenflags(dl.RTLD_NOW | dl.RTLD_GLOBAL)
于 2010-08-03T16:32:18.820 回答