Embedding Python in C, linking fails with undefined reference to `Py_Initialize'
Asked Answered
Z

6

19

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:

#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:

>>> 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 
Zoospore answered 27/12, 2014 at 23:57 Comment(3)
Try including -I/usr/include/python2.7 -lpython2.7 in the compile lineLeper
the first one is already in there and adding -lpython2.7 in the compile line does not seem to do something. It compiles fine to a object file like before but it does not link correctly. -lpython2.7 is also already added in the second gcc command for linkingZoospore
I was able to link a C an python program here. Although this loads a module not a whole program, maybe this will help.Leper
B
21

Libraries have to come after the object files when you are linking, so do:

gcc  embedpy.o $(/usr/bin/python2.7-config --ldflags)
Bankston answered 28/12, 2014 at 0:37 Comment(2)
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)Municipal
Thank you, this solved my issue in MSYS2 on Windows without adding --embed.Accroach
A
23

Also add --embed to python3-config

On Ubuntu 20.04, Python 3.8, I also needed to pass --embed to python3-config as in:

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.

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)'
Anchorage answered 13/5, 2020 at 18:42 Comment(2)
Thanks very much! the --embed is very important!!!!!!Mothball
Thank you so much for mentioning those additional flags!!! I am new to C/C++ and was trying to embed a python 3.9 program in linux, but the linker was giving me lots of unreferenced variable errors. This solution worked out! Thank you!Towage
B
21

Libraries have to come after the object files when you are linking, so do:

gcc  embedpy.o $(/usr/bin/python2.7-config --ldflags)
Bankston answered 28/12, 2014 at 0:37 Comment(2)
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)Municipal
Thank you, this solved my issue in MSYS2 on Windows without adding --embed.Accroach
T
1

Got the same error on 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:

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".

By the way, adding -fno-lto solved my problem with system-wide g++ 7.5. Possibly you can try to change version of the compiler.

Tadashi answered 15/5, 2020 at 6:57 Comment(0)
E
0

I replicated the same problem on Lubuntu14.04 32bit virtual machine running on Win7 machine.

I did the following things to replicate the problem in the first place where the C++ code is written in Eclipse C/C++ IDE. Defined a C++ Eclipse project titled "test". The source file contains the following C++ code which is the same as mentioned above by 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: In function main': /home/ros/workspace/test/src/test.cpp:15: undefined reference toPy_Initialize' /home/ros/workspace/test/src/test.cpp:17: undefined reference to PyRun_SimpleStringFlags' /home/ros/workspace/test/src/test.cpp:18: undefined reference toPy_Finalize' collect2: error: ld returned 1 exit status

The output of the following commands was the same as mentioned before by 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"::

Inside, I had the following C++ Build Settings

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

Result :: Linker errors which resulted previously from the compilation of C++ Eclipse project doesn't occur anymore.

Epigrammatist answered 17/7, 2015 at 10:4 Comment(0)
V
0

The accepted answer uses system's default library location.

If you are within an anaconda environment, library location may not be found. 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:

gcc embedpy.o -L$(python-config --prefix)/lib64 $(python-config --ldflags)
Viridity answered 18/8, 2020 at 4:7 Comment(0)
C
0

If you're on Ubuntu, you need to link python. This is the sample GCC command. I have Python 3.8 installed on my computer so I link -lpython3.8

gcc mainEncoder.c -I/usr/include/python3.8 -lpython3.8  -lm -o m.o && ./m.o
Concent answered 2/3 at 8:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.