Embed Python in C++ (using CMake) - python

I'm trying to run a python script in c++. For example:
// main.cpp
#include <python3.10/Python.h>
int main(int argc, char* argv[])
{
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is',ctime(time()))\n");
Py_Finalize();
return 0;
}
And I have such CMakeLists:
// CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(task_01)
SET(CMAKE_CXX_FLAGS "-O0")
SET(CMAKE_C_FLAGS "-O0")
set(CMAKE_CXX_STANDARD 20)
find_package (Python COMPONENTS Interpreter Development)
find_package(PythonLibs 3.10 REQUIRED)
include_directories ( ${PYTHON_INCLUDE_DIRS} )
add_executable(task_01 main.cpp)
But I get compile errors (I use CLion IDE):
undefined reference to `Py_Initialize'
undefined reference to `PyRun_SimpleStringFlags'
undefined reference to `Py_Finalize'
What am I doing wrong to run a python script?

Prefer imported targets (https://cmake.org/cmake/help/latest/module/FindPython.html#imported-targets):
cmake_minimum_required(VERSION 3.18)
project(task_01)
find_package(Python REQUIRED Development)
add_executable(task_01 main.cpp Utility.cpp Sort.cpp)
target_link_libraries(task_01 PRIVATE Python::Python)

Such configurations in CMakeLists.txt helped me:
cmake_minimum_required(VERSION 3.21)
project(task_01)
SET(CMAKE_CXX_FLAGS "-O0")
SET(CMAKE_C_FLAGS "-O0")
set(CMAKE_CXX_STANDARD 20)
find_package (Python REQUIRED
COMPONENTS Interpreter Development)
add_executable(task_01 main.cpp Utility.h Utility.cpp Sort.h Sort.cpp)
target_include_directories(${PROJECT_NAME} PRIVATE
${Python_INCLUDE_DIRS})
target_link_directories(${PROJECT_NAME} PRIVATE
${Python_LIBRARY_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE
${Python_LIBRARIES})

Related

No such file pyconfig.h in cpp proj

So, I'm trying to integrate some python code to c++ project. For that purpose I've created simple test project using clion. But met with a problem. Working on OS - Ubuntu 18.04.2
"/usr/include/boost/python/detail/wrap_python.hpp:50:11: fatal error: pyconfig.h: No such file or directory" on the line
include boost/python.hpp
Seen some solutions like:
"add export
CPLUS_INCLUDE_PATH="$CPLUS_INCLUDE_PATH:/usr/include/python2.7/" to
bashrc".
Tried that - nothing.
Here is the cmakelist
cmake_minimum_required(VERSION 3.14)
project(pythonInCPPIntegration)
set(CMAKE_CXX_STANDARD 14)
find_package(Boost 1.65.1 COMPONENTS system filesystem REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(pythonInCPPIntegration main.cpp)
target_link_libraries(pythonInCPPIntegration ${Boost_LIBRARIES})
C-proj looks like that, nothing more
#include <iostream>
#include <boost/python.hpp>
int main() {
}
Appreciate any help!
Well, it was kinda linkage problem. Solved with some manipulations over cmakelists.txt
cmake_minimum_required(VERSION 3.14)
project(pythonInCPPIntegration)
set(CMAKE_CXX_STANDARD 14)
find_package(Boost 1.65.1 COMPONENTS system filesystem REQUIRED)
find_package(PythonLibs)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${PYTHON_INCLUDE_PATH})
add_executable(pythonInCPPIntegration main.cpp)
target_link_libraries(pythonInCPPIntegration ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})

possible to compile python.exe without Visual Studio, with MinGw

I am trying to achieve things laid out on this page:
https://blogs.msdn.microsoft.com/pythonengineering/2016/04/26/cpython-embeddable-zip-file/
The code I am trying to compile is just this:
#include "Python.h"
int
wmain(int argc, wchar_t **argv)
{
return Py_Main(argc, argv);
}
In VisualStudio 15 I have to add the python/include and link to the python libs directories in the project and also add:
#include "stdafx.h"
and then it compiles and works fine. I'm just curious, is it possible to do this with mingw, or another open source C/C++ compiler?
If I place a file my_python.cpp which contains the following:
#include "include/Python.h"
int
wmain(int argc, wchar_t **argv)
{
return Py_Main(argc, argv);
}
in the root directory of a fresh 32-bit python 3.5 install (windows 7 x64), cd to that directory and try to run:
gcc my_python.cpp -Llibs -lpython35 -o my_python.exe
I get this error:
c:/mingw/bin/../lib/gcc/mingw32/5.3.0/../../../libmingw32.a(main.o):(.text.startup+0xa0): undefined reference to `WinMain#16'
Any way to fix this, get it running without Visual Studio?
The error is unrelated to Python. wmain is Visual Studio specific. GCC does not treat wmain as entry point, it just sits there as a function which never gets called.
GCC requires main or WinMain as entry point. If neither of those entry points is found, then the compiler will complain. So let's just use main as entry point.
Py_Main presumably expects wide character string input. CommandLineToArgvW will always provide that. Example:
#include <Windows.h>
#include "include/Python.h"
int main()
{
int argc;
wchar_t** argv = CommandLineToArgvW( GetCommandLineW(), &argc );
return Py_Main(argc, argv);
}
If you still get the same error, just provide WinMain entry point to make it happy
#include <Windows.h>
#include "include/Python.h"
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
int argc;
wchar_t** argv = CommandLineToArgvW( GetCommandLineW(), &argc );
return Py_Main(argc, argv);
}
Also note, *.lib files are usually for Visual Studio. GCC version expects library names with *.a extension.

Embedding Python within C++ (CPython API)

I'm trying to embed Python within my C++ project (Qt5). My project looks like this:
python_test.pro:
QT += core
QT -= gui
TARGET = python_test
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
INCLUDEPATH += C:\Tools\Python\Python35_64\include
LIBS += -LC:\Tools\Python\Python35_64\ -lpython3
main.cpp:
#include <Python.h>
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
Py_Finalize();
return a.exec();
}
When compiling I get a linker error telling me this: main.cpp:-1: Error: undefined reference to `__imp_PyRun_SimpleStringFlags'.
The funny thing is that Py_Initialize() and Py_Finalize() can be found. I read something about the define Py_LIMITED_API which hides the function PyRun_SimpleStringFlags. But I don't get it.
How am I supposed to run a Python script/file/string without these functions being available within the C API?
Setup:
Win7 Prof 64 bit
Qt 5.5.1
g++.exe (Rev1, Built by MSYS2 project) 5.3.0
Python 3.5.1 64-bit (prebuilt from https://www.python.org/downloads/release)/python-351/)
I tested this on my computer (without Qt though), with -lpython35 compiling succeeded and with -lpython3 it did not.
So
LIBS += -LC:\Tools\Python\Python35_64\ -lpython35
instead of
LIBS += -LC:\Tools\Python\Python35_64\ -lpython3

Exposing C++ to Python error from BoostPython

I'm exposing a simple C++ code to Python through BoostPython library:
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python.hpp>
using namespace boost::python;
bool test_api( void ){
return true;
};
BOOST_PYTHON_MODULE(materials) {
def( "test_api", test_api );
}
After I try to import this module, the python interpreter returns the error:
ImportError: ./example.so: undefined symbol: _Py_RefTotal
I've linked the module statically against the boost python library and the python dynamic libraries libpython3.2m.so and libpython3.2m.so.1.0 are present in the work directory.
Any suggestions on where to find the missing symbol?
The Boost libraries were not consistent with the Python installation.
cd boost_source
./bootstrap.sh --with-libraries=python --prefix=../boost_target
To configure Boost to point to the correct Python installation:
vim tools/build/v2/user-config.jam
Edit the line that points to the Python:
using python : version_number
: path_to_python_executable
: path_to_python_include_directory
: path_to_python_library_directory
Then, run the build system:
./b2
_Py_RefTotal is defined in object.h under a precompiler guard:
$less include/python3.6m/object.h
#ifdef Py_REF_DEBUG
PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
...
...
#endif /* Py_REF_DEBUG */
I was linking python3.6m but including headers from include/python3.6dm. Fixed issue including ptyhon3.6m

Python.h not found while building sample application with cmake and pybind11

I want to build simple app with pybind11, pybind is already installed in my Ubuntu system with cmake (and make install). I use this simple cmake file:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(trt_cpp_loader )
find_package(pybind11 REQUIRED)
add_executable(trt_cpp_loader main.cpp)
set_property(TARGET trt_cpp_loader PROPERTY CXX_STANDARD 11)
This is main.cpp:
#include <iostream>
#include <pybind11/embed.h>
namespace py = pybind11;
using namespace std;
int main(){return 0;}
when I build it, I get:
In file included from /usr/local/include/pybind11/pytypes.h:12:0,
from /usr/local/include/pybind11/cast.h:13,
from /usr/local/include/pybind11/attr.h:13,
from /usr/local/include/pybind11/pybind11.h:44,
from /usr/local/include/pybind11/embed.h:12,
from /home/stiv/lpr/trt_cpp_loader/main.cpp:2:
/usr/local/include/pybind11/detail/common.h:112:10: fatal error: Python.h: No such file or directory
#include <Python.h>
^~~~~~~~~~
compilation terminated.
how can I fix this problem? (python-dev and python3-dev are already installed, Python.h is available)
You'll want to use the pybind11_add_module command (see https://pybind11.readthedocs.io/en/stable/compiling.html#building-with-cmake) for the default case of creating an extension module.
If the goal is indeed to embed Python in an executable, it is your reponsibility to explicitly add python headers & libraries to the compiler/linker commands in CMake. (see https://pybind11.readthedocs.io/en/stable/compiling.html#embedding-the-python-interpreter on how to do that)
Following the Wenzel Jakob's answer I want to put an example of CMakeLists.txt for compiling the example provided in this tutorial:
// example.cpp
#include <pybind11/pybind11.h>
int add(int i, int j) {
return i + j;
}
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("add", &add, "A function which adds two numbers");
}
and
# example.py
import example
print(example.add(1, 2))
and
# CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(example)
find_package(pybind11 REQUIRED)
pybind11_add_module(example example.cpp)
now in the root run
cmake .
make
now run the python code by
python3 example.py
P.S. I have also written some instructions here for compiling/installing the pybind11.
Maybe just install the Python headers? For example, on Ubuntu you can install the sudo apt-get install python-dev (or python3-dev or pythonX.Y-dev) package. That could resolve this.

Categories

Resources