【发布时间】:2010-08-03 13:33:56
【问题描述】:
我有一个库,我使用 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++ 测试代码运行良好。
【问题讨论】:
-
我对你的代码结构有点不清楚。具体来说,我假设“主程序”实际上是 Python 解释器(即,您没有嵌入它)并且您正在尝试加载一个 .so ,它是编译时动态链接到另一个 .so 的(不是通过 dlopen()) 即时加载的,但很难说。您能否更具体地说明这些组件是什么以及它们是如何链接在一起的?
-
对不起,我不是故意的! Python 导入一个模块,这是一个由 SWIG 包装的 C++ 库。此 C++ 库使用 dlopen 和 dlsym 从用户提供的 .so 文件中获取函数。用户提供了对作为 C++ 库一部分的函数的文件调用,以便完成它的工作。从 .so 文件到 C++ 库的函数调用是失败的部分,即它们无法调用函数并简单地返回 0。但是,这种失败仅在使用 python 编写测试代码时发生。使用该库的 C++ 测试代码运行良好。
-
嗯。这是一个相当不寻常的链接场景。使用
dl模块显式加载用户提供的.so 可能值得一试(请务必先设置dl.RTLD_GLOBAL 标志)。这应该会导致链接器将 C++ 库作为依赖项加载,并且希望能够确保正确处理所有符号。不过,我没想到会遇到您首先描述的问题,所以我现在纯粹是在猜测。我只能说运行时链接配置是问题所在。 -
我已经尝试过这个并使用 dl.open 打开主 C++ 库和用户提供的库。仅打开主库并不能解决问题。还打开用户提供的库实际上会导致原始问题返回(无法找到主库中存在的符号),即使主库在之前的行中打开为 RTLD_GLOBAL。一切都只需要加载到全局范围内,就像它没有被 SWIGed 时一样。我开始认为是 SWIG 导致了这个问题。
-
好吧,在找到我自己的解决方案后,结果发现它破坏了其他一些东西,所以我根据你的建议重新尝试了我正在做的事情。我在导入模块后直接使用dl.open打开.so文件。成功!这可能与我之前使用 sys.setdlopenflags 和 dl.open 一样好。谢谢你的帮助。
标签: c++ python swig dynamic-linking