[Help Request] Embedding Python in a CPP Application Responsibly & Functionally

John McCardle mccardle.john at gmail.com
Wed Jan 25 22:31:29 EST 2023


Greetings,

I'm working on embedding a Python interpreter into a C++ application. My 
embedding example program is here, largely taken from Python docs: 
https://gist.github.com/jmccardle/f3f19d3753ae023aa52b927f0d181c43

I'm simply not interested in writing in Lua, so regardless of any 
particular downsides like `sys` in the standard library or performance 
issues, I'm committed to Python itself as what I want to hack in. This 
is for fun.

I started by compiling Python:

`./configure --enable-shared --enable-optimizations`

Then I can compile my example embedded program:

`g++ -I Python-3.11.1/Include -I Python-3.11.1 -L Python-3.11.1 -pthread 
scripting_engine.cpp libpython3.11.a -o scripteng -lm -ldl -lutil`

This is working not so bad! I can control what C++ functionality is 
exposed and I seemingly don't need anything but the Python shared object 
to execute. But the finer details of making this work truly correctly 
are eluding me.

1) To get the compiled Python to run independently, I have to hack 
LD_LIBRARY_PATH to get it to execute. `LD_LIBRARY_PATH=./Python-3.11.1 
./Python-3.11.1/python` . Even when trying to execute from the same 
directory as the binary & executable, I get an error, `/python: error 
while loading shared libraries: libpython3.11.so.1.0: cannot open shared 
object file: No such file or directory`.

2) When running the C++ program that embeds Python, I see these messages 
after initializing:
`Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>`

This is seemingly connected to some issues regarding libraries: When I 
run the Python interpreter directly, I can get some of the way through 
the process of creating a virtual environment, but it doesn't seem to 
leave me with a working pip:

`$ LD_LIBRARY_PATH=./Python-3.11.1 ./Python-3.11.1/python
 >>> import venv
 >>> venv.create("./venv", with_pip=True)
subprocess.CalledProcessError: Command 
'['/home/john/Development/7DRL/cpp_embedded_python/venv/bin/python', 
'-m', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit 
status 127.`

Meanwhile, if I try to run a script from the C++ program that includes 
`import venv`, I get a traceback about a platform library:

`Traceback (most recent call last):
   File "engine_user.py", line 7, in <module>
     import venv
   File 
"/home/john/Development/7DRL/cpp_embedded_python/Python-3.11.1/Lib/venv/__init__.py", 
line 10, in <module>
     import subprocess
   File 
"/home/john/Development/7DRL/cpp_embedded_python/Python-3.11.1/Lib/subprocess.py", 
line 104, in <module>
     from _posixsubprocess import fork_exec as _fork_exec
ModuleNotFoundError: No module named '_posixsubprocess'
`

3) I'm not sure I even need to be statically linking the interpreter.

My desired end state is this:
* Deploy a C++ program that doesn't rely on a system Python. I'm not 
sure if I need just the shared object / DLLs, or a Python executable in 
a subdirectory - I'd like to "do it the right way".
* C++ program can run a script to create a virtual environment, which 
the embedded Python environment will use. Users can activate the venv 
like any other Python environment and install packages with pip.
* ideally, some sort of "inside-out" runnable mode, where the API 
exposed by the C++ executable is available in that venv, so that I can 
test a script in Thonny or other IDE. I think I'd do this by providing a 
separate test-mode library in the venv, and when C++ executes 
`PyImport_AppendInittab("scriptable", &PyInit_scriptable);` then the 
module of the same name should be overwritten with the C++ program's 
functionality.

I've been through the embedded programming docs a bit, and they seem 
quite good as a reference, but I don't know what I'm doing well enough 
to solve my problems using them. Thanks for reading.

My ultimate goal is to expose features written in C++ for a game engine 
using SFML, and run .py files in a subdirectory to generate maps, 
control NPC dialogue and actions, etc. I'm hoping to have something 
usable for this year's 7DRL, which starts March 4th. I'd like to spend 
the time until then getting this engine working smoothly and porting it 
to Windows, so I can focus exclusively on "game content" for the 
timeboxed 7-day portion.

Kind Regards,
-John McCardle



More information about the Python-list mailing list