添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在C语言中嵌入Python,链接失败,因为对 "Py_Initialize "的引用未定义。

18 人关注

我正在尝试编译文档中的例子 https://docs.python.org/2.7/extending/embedding.html 而我的代码看起来与5.1下的代码完全一样。

#include <Python.h>
main(int argc, char *argv[])
  Py_SetProgramName(argv[0]);
  Py_Initialize();
  PyRun_SimpleString("from time import time, ctime\n"
                     "print 'Today is', ctime(time())\n");
  Py_Finalize();
  return 0;

我使用下面的命令来编译,这对我来说是很好的,并且给了我想要的对象文件。

gcc -c $(python2.7-config --cflags) embedpy.c

为了连接它,我使用了以下命令,结果出现了以下错误。

gcc $(/usr/bin/python2.7-config --ldflags) embedpy.o
embedpy.o: In function `main':
/home/miguellissimo/embedpy.c:6: undefined reference to `Py_SetProgramName'
/home/miguellissimo/embedpy.c:7: undefined reference to `Py_Initialize'
/home/miguellissimo/embedpy.c:8: undefined reference to `PyRun_SimpleStringFlags'
/home/miguellissimo/embedpy.c:11: undefined reference to `Py_Finalize'
collect2: error: ld returned 1 exit status

我找不到我做错了什么,或者我忘记了什么来使这个例子工作。

PS: python2.7-config命令在我的Xubuntu机器上有如下输出。

>>> python2.7-config --cflags 
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7  -fno-stri
ct-aliasing -D_FORTIFY_SOURCE=2 -g -fstack-protector --param=ssp-buffer-size=
4 -Wformat -Werror=format-security  -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-pr
ototypes
>>> python2.7-config --ldflags
-L/usr/lib/python2.7/config-x86_64-linux-gnu -L/usr/lib -lpthread -ldl  -luti
l -lm  -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions 
    
3 个评论
Try including -I/usr/include/python2.7 -lpython2.7 in the compile line
第一条已经在里面了,在编译行中加入-lpython2.7似乎也没有什么作用。它可以像以前一样编译成一个目标文件,但却不能正确链接。-lpython2.7也已经被添加到第二个gcc命令中,用于链接
我能够连接一个C和Python程序 here .虽然这是在加载一个模块,而不是整个程序,但也许这将会有所帮助。
python
c
python-c-extension
Miguellissimo
Miguellissimo
发布于 2014-12-28
5 个回答
nos
nos
发布于 2020-08-18
已采纳
0 人赞同

当你连接时,库必须在对象文件之后,所以要这样做。

gcc  embedpy.o $(/usr/bin/python2.7-config --ldflags)
    
CC=gcc CCFLAGS=-I /usr/include/python3.5/ -I /usr/lib/python3.5/config-3.5m-x86_64-linux-gnu/ -c -w -lpython3.5 LLFLAGS=$(/usr/bin/python3.5-config --ldflags) all: $(CC) $(CCFLAGS) TerrainPredict.c $(CC) TerrainPredict.o $(LLFLAGS)。
Ciro Santilli OurBigBook.com
Ciro Santilli OurBigBook.com
发布于 2020-08-18
0 人赞同

Also add --embed to python3-config

在Ubuntu 20.04,Python 3.8上,我还需要向python3-config传递 --embed ,如:。

gcc -std=c99 -ggdb3 -O0 -pedantic-errors -Wall -Wextra \
  -fpie $(python3-config --cflags --embed) -o 'eval.out' \
  'eval.c' $(python3-config --embed --ldflags)

否则-lpython3.8就不会被添加,从而导致定义的缺失。

这是我的测试程序。

eval.c

#define PY_SSIZE_T_CLEAN
#include <Python.h>
int main(int argc, char *argv[]) {
    (void)argc;
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    if (program == NULL) {
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    Py_SetProgramName(program);
    Py_Initialize();
    PyRun_SimpleString(argv[1]);
    if (Py_FinalizeEx() < 0) {
        exit(120);
    PyMem_RawFree(program);
    return 0;

test run:

./eval.out 'print(2 ** 3)'
    
Dan
非常感谢!--嵌入是非常重要的!!!!!!
非常感谢你提到这些额外的标志!!!我是C/C++的新手,想在linux中嵌入一个Python 3.9的程序,但链接器给了我很多未引用的变量错误。我是C/C++的新手,正试图在Linux中嵌入一个Python 3.9程序,但链接器给了我很多未引用的变量错误。这个解决方案很有效。谢谢你!"。
Rostislav Povelikin
Rostislav Povelikin
发布于 2020-08-18
0 人赞同

在WSL,Ubuntu 18.04,Python3.8,g++ 7.5上得到同样的错误。 感谢Ciro Santilli的评论,将 --embed 选项添加到 python3.8-config 中,解决了未解决的符号问题,但之后我得到了以下错误。

g++ `python3.8-config --cflags --embed` -o cpython.out cpython.cpp `python3.8-config --ldflags --embed`
lto1: fatal error: bytecode stream in file ‘/home/rpovelik/installed/miniconda3/envs/cython/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a’ generated with LTO version 6.0 instead of the expected 6.2
compilation terminated.
lto-wrapper: fatal error: g++ returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status

我想有些人也会面临同样的问题,所以我检查了类似的症状here其中conda的人说 "不要使用默认的编译器--g++。- 因为它可能导致兼容性问题--使用conda特定的编译器"。

顺便说一下,添加-fno-lto解决了我的系统范围内g++ 7.5的问题。也许你可以尝试改变编译器的版本。

Sriniwas437
Sriniwas437
发布于 2020-08-18
0 人赞同

我在Win7机器上运行的Lubuntu14.04 32位虚拟机上复制了同样的问题。

我做了以下事情来复制这个问题,首先,C++代码是在Eclipse C/C++ IDE中写的。定义了一个名为 "test "的C++ Eclipse项目。该源文件包含以下C++代码,与上面Miguellissimo提到的相同。

C++ Code ::

#include "python2.7/Python.h"
int main(int argc, char *argv[]) {
    Py_Initialize();
    PyRun_SimpleString("print \"Hello, world!\"");
    Py_Finalize();
    return 0;

Errors ::

test.o:在函数main': /home/ros/workspace/test/src/test.cpp:15: undefined reference toPy_Initialize'中。 /home/ros/workspace/test/src/test.cpp:17: 对PyRun_SimpleStringFlags' /home/ros/workspace/test/src/test.cpp:18: undefined reference toPy_Finalize的未定义引用。 collect2: error: ld returned 1 exit status

以下命令的输出与Miguellissimo之前提到的相同。

ros@rosPC:~/workspace/test/src$ python2.7-config --cflags
-I/usr/include/python2.7 -I/usr/include/i386-linux-gnu/python2.7  -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security  -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes
ros@rosPC:~/workspace/test/src$ python2.7-config --ldflags
-L/usr/lib/python2.7/config-i386-linux-gnu -L/usr/lib -lpthread -ldl  -lutil -lm  -lpython2.7 -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions

Project Properties of C++ Eclipse Project titled "test"::

在里面,我有以下的C++构建设置

GCC C++ Compiler

Command: g++
All options: -I/opt/ros/indigo/include -O0 -g3 -Wall -c -fmessage-length=0
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Includes
    include paths: /opt/ros/indigo/include

GCC C Compiler

Command: gcc
All options: -I/opt/ros/indigo/include -I/usr/lib/python2.7/config-i386-linux-gnu -O0 -g3 -Wall -c -fmessage-length=0
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Includes
    include paths: /opt/ros/indigo/include
                   /usr/lib/python2.7/config-i386-linux-gnu

GCC C++ Linker

Command: g++
All options: Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Libraries:
    Libraries(-I): 
    Library search path(-L): 

Solution::

Specified the following C++ Build Settings in the Project Properties of C++ Eclipse Project "test"

GCC C++ Compiler

Command: g++
All options: -I/opt/ros/indigo/include -I/usr/include/python2.7 -O0 -g3 -Wall -c -fmessage-length=0
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Includes
    include paths: /opt/ros/indigo/include
                   /usr/include/python2.7

GCC C Compiler

Command: gcc
All options: -I/opt/ros/indigo/include -I/usr/include/python2.7 -O0 -g3 -Wall -c -fmessage-length=0
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Includes
    include paths: /opt/ros/indigo/include
                   /usr/include/python2.7

GCC C++ Linker

Command: g++
All options: -L/usr/lib/python2.7/config-i386-linux-gnu
Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
Libraries:
    Libraries(-I): python2.7
    Library search path(-L): /usr/lib/python2.7/config-i386-linux-gnu

结果 :: 以前在编译C++ Eclipse项目时产生的链接器错误不再发生了。

bJust
bJust
发布于 2020-08-18
0 人赞同

接受的答案是使用系统的默认库位置。

如果你在Anaconda环境中,可能找不到库的位置。我倾向于在链接时更明确地给出位置,比如。