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 
3
  • 3
    Try including -I/usr/include/python2.7 -lpython2.7 in the compile line Commented Dec 28, 2014 at 0:16
  • 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 linking Commented Dec 28, 2014 at 0:23
  • 1
    I was able to link a C an python program here. Although this loads a module not a whole program, maybe this will help. Commented Dec 28, 2014 at 0:29

7 Answers 7

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)'
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks very much! the --embed is very important!!!!!!
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!
22

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

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

2 Comments

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)
Thank you, this solved my issue in MSYS2 on Windows without adding --embed.
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.

Comments

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.

Comments

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)

Comments

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

Comments

0

On windows I came across this error. When I linked the library I needed to specify the correct library name. ie -lpython313 instead of -lpython3.

broken:

g++.exe -I"$env:PYTHON_HOME/include" -L"$env:PYTHON_HOME" -lpython3 .\py_zap.c -o py_zap.exe

working:

g++.exe -I"$env:PYTHON_HOME/include" -L"$env:PYTHON_HOME" -lpython313 .\py_zap.c -o py_zap.exe

Oddly enough I could link some of the python function with just -lpython3

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.