我在共享库插件中使用 boost::python 来运行一些 python 代码。
我的主程序使用 boost::dll::shared_library API 在运行时将共享库作为插件加载。即我的主程序未与共享库插件链接。
我的代码在 Ubuntu 20.04 上运行。
我正在将我的共享库与 Python 链接:
my_shared_lib/CMakeLists.txt
:
find_package(Python3 COMPONENTS Development NumPy REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE ${Python3_LIBRARIES} Python3::NumPy)
从我的共享库运行以下代码时,我收到导入错误:
#include <boost/python.hpp>
Py_Initialize();
namespace np = boost::python::numpy;
np::initialize(); //ImportError here
我收到以下错误:
导入错误:/home/myuser/.local/lib/python3.8/site-packages/numpy/core/_multiarray_umath.cpython-38-x86_64-linux-gnu.so:未定义符号:PyObject_SelfIter
我确认我的
/usr/lib/x86_64-linux-gnu/libpython3.8.so
中有 LD_LIBRARY_PATH
。
当我的主程序与 Python 链接时,程序正常运行,没有导入错误
main_program/CMakeLists.txt
:
find_package(Python3 COMPONENTS Development NumPy REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE ${Python3_LIBRARIES} Python3::NumPy)
我这里的结论是,在运行时加载共享库插件似乎没有加载
libpython3.8.so
,而在主程序中加载libpython3.8.so使其可供共享库插件使用。
如果我像这样手动加载
libpython3.8.so
在我的共享库中:
#include <boost/python.hpp>
#include <dlfcn.h>
dlopen("/usr/lib/x86_64-linux-gnu/libpython3.8.so", RTLD_LAZY | RTLD_GLOBAL);
Py_Initialize();
namespace np = boost::python::numpy;
np::initialize();
我一路上遇到了不同的错误:
回溯(最近一次调用最后一次):
文件“/home/myuser/.local/lib/python3.8/site-packages/numpy/core/init.py”,第 23 行,位于
从 。导入多数组
文件“/home/myuser/.local/lib/python3.8/site-packages/numpy/core/multiarray.py”,第 10 行,位于
从 。导入覆盖
文件“/home/myuser/.local/lib/python3.8/site-packages/numpy/core/overrides.py”,第 6 行,位于
从 numpy.core._multiarray_umath 导入(ImportError:PyCapsule_Import 无法导入模块“datetime”
如何让我的共享库插件在加载时自动加载libpython3.8.so?
编辑
使用 gdb 我发现我最初的假设是错误的。当主应用程序加载我的共享库插件时,它还会加载 libpython3.8.so.1.0。 已加载已加载'/home/myuser/.vs/mainapp/build/plugins/libap_python_ detector.so'。符号已加载。 已加载“/usr/local/3rdparty/hpc/5.13.0-39_AMD_EPYC/boost176/build/lib/libboost_numpy38.so.1.76.0”。符号已加载。 已加载“/lib/x86_64-linux-gnu/libpython3.8.so.1.0”。符号已加载。 已加载“/usr/local/3rdparty/hpc/5.13.0-39_AMD_EPYC/boost176/build/lib/libboost_python38.so.1.76.0”。符号已加载。
加载 numpy 出了什么问题?
目前,NumPy 不支持从嵌入共享库中的 Python 解释器加载 NumPy 的设计。 (请参阅排除导入错误 。它不涵盖您的场景。)
发生该错误是因为 NumPy 共享库几乎没有链接到 Python 运行时库。 (您可以使用 ldd 检查它。)
但至少在 Linux 上,您可以通过使用 RTLD_GLOBAL 标志手动加载 Python 运行时库来解决此问题,如下例所示。 (在主程序中加载运行时库,而不是在插件中。当然,只有在加载依赖于 Numpy 的插件时才需要这样做。)
#include <dlfcn.h>
int main()
{
...
// When you load a NumPy-dependent plugin, do the following just before that.
dlopen("libpython3.8.so", RTLD_LAZY | RTLD_GLOBAL);
...
}
但我不确定它将来不会坏掉。