【发布时间】:2018-01-26 13:59:30
【问题描述】:
我的情况是我有一个可执行文件 (main.c),它动态加载一个共享对象 (py_plugin.c),而共享对象又链接到 python。
但是,当 python 插件尝试导入其依赖项未链接到 libpython 的模块时,我收到以下错误:
ImportError: /usr/lib/python2.7/lib-dynload/bz2.x86_64-linux-gnu.so: undefined symbol: PyExc_SystemError
据我推断,这意味着库 bz2.x86_64-linux-gnu.so 无权访问 python 符号。
请注意,该错误是特定于“bz2”包的,因为我在问题末尾使用最小的工作示例强制它浮出水面。在那里,我正在执行“bz2”的显式导入,它在 python 插件 (py_plugin.c) 中加载库 bz2.x86_64-linux-gnu.so。
查看我验证的依赖项:
-
库
bz2.x86_64-linux-gnu.so没有链接到pythonusr@cmptr $ ldd /usr/lib/python2.7/lib-dynload/bz2.x86_64-linux-gnu.so linux-vdso.so.1 => (0x00007ffd511fb000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f8c63a0a000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c6362a000) libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0 (0x00007f8c6341a000) /lib64/ld-linux-x86-64.so.2 (0x00007f8c63e33000) -
但是我的python插件是:
usr@cmptr $ ldd py_plugin.so linux-vdso.so.1 => (0x00007ffc1ef5c000) libpython2.7.so.1.0 => /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0 (0x00007f56ac01c000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f56abc3c000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f56aba1d000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f56ab800000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f56ab5fc000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f56ab3f8000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f56ab0a2000) /lib64/ld-linux-x86-64.so.2 (0x00007f56ac79a000)
我的问题如下:
问题本身就很明显,但是为什么我的插件明明链接到libpython的时候python符号不可用?
-
当我可以不将 python 链接到主可执行文件(它是预编译的二进制文件)时,是否有人知道如何解决此问题?
李>
来自this e-mail thread 我了解到错误的根源可能是因为 python 的分发理念不同(我正在运行基于 Ubuntu 的发行版)。这个bug report 也突出了这个问题。
产生错误的例子
生成库/执行程序
gcc $(pkg-config --cflags python) -shared -o py_plugin.so py_plugin.c $(pkg-config --libs python)
gcc -o main main.c -lltdl
我系统上 pkg-config 的 putput 是:
pkg-config --cflags python
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7
pkg-config --libs python
-lpython
文件: main.c
#include <ltdl.h>
#include <stdio.h>
typedef int(*dyn_fptr)();
int main()
{
if(lt_dlinit()) {
return -1;
}
lt_dlhandle handle = lt_dlopen("./py_plugin.so");
dyn_fptr func = (dyn_fptr)lt_dlsym(handle, "func");
int a = func(); // <----------------------------------- Call "func" in py_plugin
lt_dlclose(handle);
return 0;
}
文件: py_plugin.c
#include <Python.h>
int func()
{
Py_Initialize();
PyObject *pName = PyString_FromString("bz2");
PyObject *pModule = PyImport_Import(pName); // <--------------------- ERROR
Py_DECREF(pName);
if(!pModule) {
PyErr_Print();
}
Py_Finalize();
return 0;
}
【问题讨论】:
-
也许,问题就像您链接的论坛所说的那样简单。 Debian 和从它派生的发行版经常破坏 LSB,然后一切都以不同的方式和以意想不到的方式布局。但我很好奇!为什么要从 c 调用 python 插件?
-
另外,如果你直接从 python 脚本
import bz2会发生什么? -
@IharobAlAsimi 当我简单地导入“bz2”时一切正常,因为 python 可执行文件(静态)链接到 libpython,因此模块可以直接从可执行文件访问符号。至于“为什么使用 C 语言的 python?” C 库是为(科学)应用程序之间的可移植性而设计的,我们使用 python 来执行典型的动态任务。每当它想做一些“花哨的”事情时,想想 C 中的数据将自身映射到 Python 对象。
-
@IharobAlAsimi 你说得对,这个问题只是 Debian 特有的,Fedora 按预期处理了这个问题。
标签: python c plugins shared-libraries dynamic-loading