numpy 从C++共享库调用Python代码

gk7wooem  于 2023-10-19  发布在  Python
关注(0)|答案(1)|浏览(147)

我在一个共享库插件中使用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)

当从我的共享库运行以下代码时,我得到一个ImportError:

#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
我验证了我的LD_LIBRARY_PATH上有/usr/lib/x86_64-linux-gnu/libpython3.8.so。
当将我的主程序与Python链接时,程序OK运行时不带ImportError 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行,来自。import multiarray File“/home/myuser/.local/lib/python3.8/site-packages/numpy/core/multiarray.py“,line 10,in from . import overrides File“/home/myuser/.local/lib/python3.8/site-packages/numpy/core/overrides.py“,line 6,in from numpy.core._multiarray_umath import(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/boost 176/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/boost 176/build/lib/libboost_python38.so.1.76.0”。符号加载完毕。
所以加载numpy有什么不对吗?

yhived7q

yhived7q1#

目前,NumPy不支持从嵌入在共享库中的Python解释器加载NumPy的设计。(参见Troubleshooting ImportError。它不包括你的场景)。
发生此错误是因为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);
    ...
}

但我不确定它将来不会被打破。

相关问题