在C中嵌入Python时,链接失败,引用未定义为'Py#u Initialize';

在C中嵌入Python时,链接失败,引用未定义为'Py#u Initialize';,python,c,python-c-extension,Python,C,Python C Extension,我试图从文档中编译示例,我的代码与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

我试图从文档中编译示例,我的代码与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;
}
要链接它,我使用以下命令,该命令最终导致以下错误:

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 

链接时,库必须位于对象文件之后,因此:

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

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

在C++ Eclipse C/C++开发环境中编写C++代码的第一个地方,我做了以下的事情来复制这个问题。定义了一个名为“test”的C++ Eclipse项目。源文件包含以下C++代码,与上面提到的MiguelsiSimo相同。 C++代码::

#include "python2.7/Python.h"

int main(int argc, char *argv[]) {

    Py_Initialize();
    PyRun_SimpleString("print \"Hello, world!\"");

    Py_Finalize();
    return 0;
}
错误::

测试o:在函数
main'中:
/home/ros/workspace/test/src/test.cpp:15:未定义的引用
/home/ros/workspace/test/src/test.cpp:17:PyRun\u SimpleStringFlags的未定义引用
/home/ros/workspace/test/src/test.cpp:18:未定义对
Py_Finalize'的引用 collect2:错误:ld返回了1个退出状态

以下命令的输出与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
< C++ Eclipse项目名为“test”的项目属性::

内部,我有以下C++构建设置

GCC C++编译器< /P>

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

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
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++链接器< /P>
Command: g++

All options: Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}

Libraries:

    Libraries(-I): 

    Library search path(-L): 
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项目“测试”

项目属性中指定以下C++生成设置

GCC C++编译器< /P>

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

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
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++链接器< /P>
Command: g++

All options: Command line pattern: ${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}

Libraries:

    Libraries(-I): 

    Library search path(-L): 
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++编译程序中以前出现的链接错误不再发生。

< P> <强>也添加<代码>嵌入 > <代码> Python 3配置> <代码> <强> < /P> 在Ubuntu20.04和python3.8上,我还需要将
--embed
传递给python3配置,如下所示:

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
,这会导致缺少定义

这是我的测试程序:

评估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;
}

在WSL、Ubuntu18.04、Python3.8、g++7.5上也出现了同样的错误。 多亏了Ciro Santilli的评论,将
--embed
选项添加到
python3.8-config
解决了未解决的符号问题,但在此之后,我得到了以下错误:

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
g++`python3.8-config--cflags--embed`-o cpython.out cpython.cpp`python3.8-config--ldflags--embed`
lto1:致命错误:文件“/home/rpovelik/installed/miniconda3/envs/cython/lib/python3.8/config-3.8-x86_64-linux-gnu/libpython3.8.a”中的字节码流是用LTO版本6.0而不是预期的6.2生成的
编译终止。
lto包装器:致命错误:g++返回1个退出状态
编译终止。
/usr/bin/ld:错误:lto包装失败
collect2:错误:ld返回了1个退出状态
我想有些人会面临同样的问题,所以我检查了conda的类似症状,他们说“不要使用默认编译器-
g++
,因为这可能会导致兼容性问题-使用conda特定的编译器”


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

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

如果您在蟒蛇环境中,可能找不到库位置。我倾向于在链接过程中更明确地给出位置,例如:

gcc embedpy.o -L$(python-config --prefix)/lib $(python-config --ldflags)
这在64位库中的anaconda环境之外不起作用,在这种情况下:

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

尝试在编译行中包含
-I/usr/include/python2.7-lpython2.7
。第一个已经在那里了,在编译行中添加-lpython2.7似乎没有什么作用。它可以像以前一样编译为对象文件,但链接不正确-lpython2.7也已经添加到用于linkingI的第二个gcc命令中,我能够将C链接到python程序。虽然这会加载一个模块而不是整个程序,但这可能会有所帮助。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)所有:$(CC)$(CCFLAGS)TerrainPredict.c$(CC)TerrainPredict.o$(LLFLAGS)非常感谢!嵌入是非常重要的!!!!!!