简体   繁体   English

在 C 中嵌入 Python,链接失败,未定义对“Py_Initialize”的引用

[英]Embedding Python in C, linking fails with undefined reference to `Py_Initialize'

I am trying to compile the example from the docs https://docs.python.org/2.7/extending/embedding.html and my code looks exactly like the one under 5.1:我正在尝试从文档https://docs.python.org/2.7/extending/embedding.html编译示例,我的代码看起来与 5.1 下的完全一样:

#include <Python.h>

int
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;
}

I use the following command to compile it which works fine for me and gives me the desired object file:我使用以下命令编译它,这对我来说很好用,并为我提供了所需的目标文件:

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

To link it I use the following command which ends up in the following error:要链接它,我使用以下命令,最终出现以下错误:

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

I can't find out what I am doing wrong or what I forget to get the example working.我无法找出我做错了什么或忘记让示例工作的原因。

PS: The python2.7-config command gives the following output on my Xubuntu machine: 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 

链接时,库必须在目标文件之后,所以这样做:

gcc  embedpy.o $(/usr/bin/python2.7-config --ldflags)

Also add --embed to python3-config还要添加--embedpython3-config

On Ubuntu 20.04, Python 3.8, I also needed to pass --embed to python3-config as in:在 Ubuntu 20.04、Python 3.8 上,我还需要将--embed传递给 python3-config,如下所示:

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

otherwise -lpython3.8 is not added which leads to missing definitions.否则-lpython3.8不会被添加,这会导致定义丢失。

This is my test program:这是我的测试程序:

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)'

I replicated the same problem on Lubuntu14.04 32bit virtual machine running on Win7 machine.我在 Win7 机器上运行的 Lubuntu14.04 32 位虚拟机上复制了同样的问题。

I did the following things to replicate the problem in the first place where the C++ code is written in Eclipse C/C++ IDE.我做了以下事情来复制问题,首先在 Eclipse C/C++ IDE 中编写 C++ 代码。 Defined a C++ Eclipse project titled "test".定义了一个名为“test”的 C++ Eclipse 项目。 The source file contains the following C++ code which is the same as mentioned above by Miguellissimo.源文件包含以下与 Miguellissimo 提到的相同的 C++ 代码。

C++ Code :: C++ 代码 ::

#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: In function main': /home/ros/workspace/test/src/test.cpp:15: undefined reference to Py_Initialize' /home/ros/workspace/test/src/test.cpp:17: undefined reference to PyRun_SimpleStringFlags' /home/ros/workspace/test/src/test.cpp:18: undefined reference to Py_Finalize' collect2: error: ld returned 1 exit status test.o: 在函数main': /home/ros/workspace/test/src/test.cpp:15: undefined reference to Py_Initialize' /home/ros/workspace/test/src/test.cpp:17: 未定义引用到PyRun_SimpleStringFlags' /home/ros/workspace/test/src/test.cpp:18: undefined reference to Py_Finalize' collect2 的PyRun_SimpleStringFlags' /home/ros/workspace/test/src/test.cpp:18: undefined reference to :错误:ld 返回 1 个退出状态

The output of the following commands was the same as mentioned before by Miguellissimo,以下命令的输出与 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"::标题为“test”的 C++ Eclipse 项目的项目属性::

Inside, I had the following C++ Build Settings在里面,我有以下 C++ 构建设置

GCC C++ Compiler GCC C++ 编译器

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 GCC C 编译器

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 GCC C++ 链接器

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"在 C++ Eclipse 项目“test”的项目属性中指定了以下 C++ 构建设置

GCC C++ Compiler GCC C++ 编译器

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 GCC C 编译器

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 GCC C++ 链接器

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

Result :: Linker errors which resulted previously from the compilation of C++ Eclipse project doesn't occur anymore.结果 :: 之前编译 C++ Eclipse 项目导致的链接器错误不再发生。

Got the same error on WSL, Ubuntu 18.04, Python3.8, g++ 7.5.在 WSL、Ubuntu 18.04、Python3.8、g++ 7.5 上遇到同样的错误。 Thanks to Ciro Santilli comment, adding --embed option to python3.8-config solved unresolved symbols problem, but after that I got the following error:感谢 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

I suppose some people are going to face the same issue so I inspected the similar symptoms here where conda people said something like "don't use default compilers - g++ - because it could cause compatibility issues - use conda specific compilers".我想有些人会面临同样的问题,所以我在这里检查了类似的症状其中 conda 人说“不要使用默认编译器 - g++ - 因为它可能导致兼容性问题 - 使用 conda 特定的编译器”。

By the way, adding -fno-lto solved my problem with system-wide g++ 7.5 .顺便说一句,添加-fno-lto解决了我的系统范围g++ 7.5 Possibly you can try to change version of the compiler.可能您可以尝试更改编译器的版本。

The accepted answer uses system's default library location.接受的答案使用系统的默认库位置。

If you are within an anaconda environment, library location may not be found.如果您在 anaconda 环境中,则可能找不到库位置。 I tend to give locations more explicitly during linking, like:我倾向于在链接期间更明确地给出位置,例如:

gcc embedpy.o -L$(python-config --prefix)/lib $(python-config --ldflags)

This will not work outside anaconda environment in 64-bit library, in which case:这在 64 位库中的 anaconda 环境之外不起作用,在这种情况下:

gcc embedpy.o -L$(python-config --prefix)/lib64 $(python-config --ldflags)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM