I'm embedding Python into a C++ project with example code from https://docs.python.org/3/extending/embedding.html#very-high-level-embedding:
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.20)
project(python_in_cpp)
set(CMAKE_CXX_STANDARD 11)
# sudo apt install libpython3.11-dev
find_package(PythonLibs 3.11 REQUIRED)
find_package(Python COMPONENTS Interpreter Development)
message("Python_FOUND:${Python_FOUND}")
message("Python_VERSION:${Python_VERSION}")
message("Python_Development_FOUND:${Python_Development_FOUND}")
message("Python_LIBRARIES:${Python_LIBRARIES}")
include_directories(${Python_INCLUDE_DIRS})
link_directories(
${Python3_LIBRARY_DIRS}
${Python3_RUNTIME_LIBRARY_DIRS}
)
link_libraries(${Python3_LIBRARIES})
add_executable(python_in_cpp main.cpp)
main.cpp
:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
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); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
CMake log shows that both Python
and PythonLibs
found but when compiling, I got errors about several undefined reference:
main.cpp:(.text+0x1f): undefined reference to `Py_DecodeLocale'
/usr/bin/ld: main.cpp:(.text+0x63): undefined reference to `Py_SetProgramName'
/usr/bin/ld: main.cpp:(.text+0x68): undefined reference to `Py_Initialize'
/usr/bin/ld: main.cpp:(.text+0x7c): undefined reference to `PyRun_SimpleStringFlags'
/usr/bin/ld: main.cpp:(.text+0x81): undefined reference to `Py_FinalizeEx'
/usr/bin/ld: main.cpp:(.text+0x9e): undefined reference to `PyMem_RawFree'
How do I fix it to build this project?
I have several python installed:
$ apt list --installed | grep "lib*python"
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
libpython3-dev/stable,now 3.11.2-1+b1 amd64 [installed]
libpython3-stdlib/stable,now 3.11.2-1+b1 amd64 [installed,automatic]
libpython3.11-dev/stable-security,now 3.11.2-6+deb12u3 amd64 [installed]
libpython3.11-minimal/stable-security,now 3.11.2-6+deb12u3 amd64 [installed,automatic]
libpython3.11-stdlib/stable-security,now 3.11.2-6+deb12u3 amd64 [installed,automatic]
libpython3.11/stable-security,now 3.11.2-6+deb12u3 amd64 [installed,automatic]
It's a stupid typo. You printed Python_LIBRARIES
but you used Python3_LIBRARIES
in your link_libraries
statement.
To avoid these kind of issues in the future, you should prefer using imported targets if they are provided by the modules.
You can replace your three statements (include_directories
, link_directories
and link_libraries
) with just this one line:
target_link_libraries(python_in_cpp PUBLIC Python::Python)
Make sure to put that after the add_executable
statement.