我有以下需要与Python集成的C程序:
#include <Python.h>
PyObject* get_details(){
PyObject *details = PyDict_New();
PyObject *key, *value;
key = PyUnicode_FromString("full name");
value = PyUnicode_FromString("Pete Graham");
PyDict_SetItem(details, key, value);
return details;
}
我可以使用:
在OS X上编译程序gcc -I /Library/Frameworks/Python.framework/Versions/3.4/Headers \
-L /Library/Frameworks/Python.framework/Versions/3.4/lib \
-lpython3.4 get_person_dict.c
当我尝试在Ubuntu /usr/bin/ld: cannot find -lpython3.4.
这是我在Ubuntu上使用的命令我已经为python lib路径尝试了各种值。
gcc -I /usr/include/python3.4 \
-L /usr/local/lib \
-lpython3.4 get_person_dict.c
我安装了带有sudo apt-get install python3.4-dev
版本的Ubuntu trusty64的python,并且正在Vagrant上使用。
答案 0 :(得分:5)
有几件事是错误的。
正如@JJHakala告诉你的那样,
python3.4-config --libs
将告诉您将可执行文件与Python 3.4链接所需的库 运行时,即:
-lpython3.4m -lpthread -ldl -lutil -lm
和
python3.4-config --ldflags
会告诉你所有你必须传递给链接器以实现的选项 同样的结果,即:
-L/usr/lib/python3.4/config-3.4m-x86_64-linux-gnu \
-L/usr/lib -lpython3.4m -lpthread -ldl -lutil -lm \
-Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
因此,让我们尝试将这些链接器选项放入您的gcc命令行而不是 您使用过的链接器选项。你的命令行是:
$ gcc -I /usr/include/python3.4 -L/usr/local/lib -lpython3.4 get_person_dict.c
带链接器选项:
-L/usr/local/lib -lpython3.4
所以我们会尝试:
$ gcc -I /usr/include/python3.4 `python3.4-config --ldflags` get_person_dict.c
这不起作用。输出是:
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
/build/buildd/glibc-2.21/csu/../sysdeps/x86_64/start.S:114: undefined reference to `main'
/tmp/ccrczTMI.o: In function `get_details':
get_person_dict.c:(.text+0x9): undefined reference to `PyDict_New'
get_person_dict.c:(.text+0x17): undefined reference to `PyUnicode_FromString'
get_person_dict.c:(.text+0x25): undefined reference to `PyUnicode_FromString'
get_person_dict.c:(.text+0x40): undefined reference to `PyDict_SetItem'
collect2: error: ld returned 1 exit status
我们对所有调用的Python 3.4函数都有未定义的引用
get_person_dict.c
,以及对main
未定义的Python 3.4引用的原因是,
仍然是,在任何调用其中定义的函数的文件之前将库传递给链接器。所以
链接器依次进入命令行上的每个库并对自己说:
我是否注意到对此库中具有定义的未定义函数的任何调用?
不。然后我不需要链接此库中的任何内容。并传递。
在忽略所有库之后,它会到达您的get_person_dict.c
(或者在...中)
现实,编译器具有的临时目标文件/tmp/ccrczTMI.o
以前从get_person_dict.c
汇编而来。发现未定义
引用PyDict_New
,PyUnicode_FromString
PyUnicode_FromString
,
PyDict_SetItem
。但是现在没有剩下可以定义它们的库。
他们 定义的库是桥下的水,所以
未定义的引用仍然是链接错误。
在链接序列中,需要定义的文件必须在之前出现 提供定义的文件。
那很容易纠正:
$ gcc -I /usr/include/python3.4 get_person_dict.c `python3.4-config --ldflags`
现在输出是:
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
/build/buildd/glibc-2.21/csu/../sysdeps/x86_64/start.S:114: undefined reference to `main'
collect2: error: ld returned 1 exit status
链接器现在已经找到了所有Python 3.4函数的定义。但它
仍然说它无法找到main
的定义。
原因是你发布的C“程序”不是程序,它是
只是函数PyObject* get_details()
的定义。每个C程序,
根据定义,它有一个main
函数,这是第一个被调用的函数。对于
这个原因,当您尝试将一些文件和库链接到C程序时,
正如您尝试的那样,链接器会自动链接调用的启动代码
main
。但你没有main
。
所以你不能将你的get_person_dict.c
链接为一个程序,即使你得到了
联系顺序权。您可以编译它,而无需链接它:
$ gcc -I /usr/include/python3.4 -c -o get_person_dict.o get_person_dict.c
它为您提供了一个包含已编译的对象文件get_person_dict.o
,但是
没有关联,PyObject* get_details()
的定义。它将与之相同
gcc为你编译的临时目标文件/tmp/ccrczTMI.o
而不是
告诉我上面的编译和链接尝试失败。
但是在编译了get_person_dict.o
之后,您可以将 链接到其中
一个程序,只要你还链接 - 之后 - 其他库那个
定义它调用的函数:
<强> get_person_prog.c 强>
#include <Python.h>
#include <stdio.h>
extern PyObject * get_details(); // Ought to be put in a header
int main(void)
{
PyObject * pyobj = get_details();
if (pyobj) {
puts("Got the details");
}
return 0;
}
编译:
$ gcc -I /usr/include/python3.4 -c -o get_person_prog.o get_person_prog.c
按正确的顺序链接目标文件和库,以制作程序prog
:
$ gcc -o prog get_person_prog.o get_person_dict.o `python3.4-config --ldflags`
执行命令
$ ./prog
Got the details
答案 1 :(得分:1)
在debian / jessie中
python3.4-config --ldflags
告诉我应该使用哪些链接参数,这些参数也适用于Ubuntu。该命令位于python3.4-dev
包中。
python3.4-config --libs
告诉链接时所需库的名称。
输出
-L/usr/lib/python3.4/config-3.4m-x86_64-linux-gnu -L/usr/lib -lpython3.4m
-lpthread -ldl -lutil -lm -Xlinker -export-dynamic
-Wl,-O1 -Wl,-Bsymbolic-functions`
包含-lpython3.4m
,但问题中不包含-lpython3.4
。使用它应该有助于解决这个特定的问题。