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
Libraries have to come after the object files when you are linking, so do:
gcc embedpy.o $(/usr/bin/python2.7-config --ldflags)
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 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
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.
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.
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)
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)'