1

I'm designing musical training games using JUCE -- a multiplatform C++ framework that allows me to code audio/visuals close to the wire.

However, I have coded my gameplay (control flow / data-processing) in Python -- it is complex and I wish to keep changing it so I can experiment with different gameplays. Python is ideal for this kind of rapid prototyping work.

So I would like my (platform independent, so Win/OSX/Lin/iOS/And) C++ to start up a Python runtime, feed it a .py file, and then call various functions in that .py. Also I would like to be able to call back to the C++ code from the .py.

Here is the relevant official Python documentation: https://docs.python.org/2/extending/extending.html

And here is a CodeProject article: http://www.codeproject.com/Articles/11805/Embedding-Python-in-C-C-Part-I

However, neither of them seem to address the issue of multiplatform.

The technique seems to be to link with the library libpython.a, and #include which contains the various functions for starting up the runtime environment, loading scripts, executing python-code, etc.

But surely this libpython.a would need to be compiled separately per platform? If so, this wouldn't be a very clean solution, so could I instead add the Python source code to my project and get it to compile the .a?

How can I go about doing this?

EDIT: https://wiki.python.org/moin/boost.python/EmbeddingPython

EDIT2: I'm pretty sure trying to bring in the full CPython source code is overkill here -- someone must have made some stripped down Python implementation in C/C++ that doesn't support any system-calls/multithreading/fancy-stuff -- just works through Python syntax line by line. Looking thru https://wiki.python.org/moin/PythonImplementations but I can't see an obvious candidate.

EDIT3: https://github.com/micropython/micropython should be added to that last page, but still it doesn't look like it is what I'm after

P i
  • 29,020
  • 36
  • 159
  • 267
  • 1
    The `.a` is part of Python itself (or part of a `python-dev` or similar package, on linux distros that like to break programs up into pieces), or something you build manually out of the Python sources if you want a custom Python build. And yes, of course it needs to be compiled separately per platform. Just like your C++ code does (except that you can use standard pre-built libraries for Python, and obviously nobody's distributed pre-built libraries of your C++ code). How would you expect that to work otherwise? – abarnert Aug 29 '14 at 23:40
  • Does it have to be python? There are other scripting languages that were explicitly designed to be embedded into other Applications. They make the embedding process much easier, give the programmer more control over the runtime and are just more lightweight in general. See Lua, Squirrel and Guile for examples. The Lua and Squirrel source code will let you get away without having a different library built for every platform. Porting your existing work to these languages might be a pain though. – BlamKiwi Sep 08 '14 at 02:35
  • This question really belongs on [SoftwareRecs.SE](http://softwarerecs.stackexchange.com/) and isn't a good question for Stack Overflow's intended use. That being said, SO gets much more traffic, so I can't blame you for posting here instead. – Poik Sep 11 '14 at 15:04

3 Answers3

3

There's an entire chapter of the Python docs that explain the different approaches you can take embedding a Python interpreter into another app.

Embedding Python is similar to extending it, but not quite. The difference is that when you extend Python, the main program of the application is still the Python interpreter, while if you embed Python, the main program may have nothing to do with Python — instead, some parts of the application occasionally call the Python interpreter to run some Python code.

So if you are embedding Python, you are providing your own main program. One of the things this main program has to do is initialize the Python interpreter. At the very least, you have to call the function Py_Initialize(). There are optional calls to pass command line arguments to Python. Then later you can call the interpreter from any part of the application.

There are several different ways to call the interpreter: you can pass a string containing Python statements to PyRun_SimpleString(), or you can pass a stdio file pointer and a file name (for identification in error messages only) to PyRun_SimpleFile(). You can also call the lower-level operations described in the previous chapters to construct and use Python objects.

A simple demo of embedding Python can be found in the directory Demo/embed/ of the source distribution.

bgporter
  • 35,114
  • 8
  • 59
  • 65
  • 1
    I have already looked through this documentation; it says I must link "libpython.a" to my C/C++ project, then #include "python.h", then I will have access to Py_Initialize() and friends. But I don't like the idea of having to supply a different libpython.a for each platform I'm targeting. – P i Aug 29 '14 at 18:40
  • 3
    @Pi: Do you not understand what linking means? You don't supply `libpython.a`. If you're distributing binaries, your program will have `libpython.a` statically linked into it. If you're distributing source, your program will presumably require a Python dev environment to link against. – abarnert Aug 29 '14 at 23:37
  • Relying on system pythons is a path to madness. On windows you have no idea what version they've installed , and where its installed. On Macs and Linux boxen while theres a good chance you'll have a 2.7, you can't guarantee it, nor that its built in a way that suits your software. Your much better off statically linking in a python of your own. That way you have full control over dependencies. Its *easier* that way. Its just another dependency and your build system just needs to add it in. – Shayne Sep 30 '18 at 11:22
0

I recently decided to create a project that mixes C++ with Python, thus getting the best of both worlds. My idea was to do rapid prototyping of classes and functions in Python for obvious reasons, but still being able to call C++ code within Python (for obvious reasons as well). So instead of embedding Python in the C++ framework, I suggest you do the opposite: embed your C++ framework into a Python project. In order to do so, you just have to write very simple interface files and let Swig take care of the interfacing part.

If you want to start from scratch, there's a nice tool called cookiecutter that can be used to generate a project templates. You can choose either the cookiecutter-pypackage, or the cookiecutter-pylibrary, the latter improving over the former as described here. Interestingly, you can also use the cookiecutter code to generate the structure of a C++ project. This empty project uses the CMake build system, which IMHO is the best framework for developing platform independent C++ code. I then had to decide on the directory structure for this mixed project, so one of my previous posts describes this in detail. Good luck!

Community
  • 1
  • 1
aaragon
  • 2,314
  • 4
  • 26
  • 60
0

I'm using SWIG to embed Python into my C++ application, and to extend it as well, i.e. access my C++ API in Python outside my application. SWIG and Python are multi-platform, so that is not really an issue. One of the main advantage of SWIG is that it can generate bindings for a lot of languages. There are also a lot of C++ code wrappers that could be used, for example boost.python or cython.

Check these links on SO:

Extending python - to swig, not to swig or Cython

Exposing a C++ API to Python

Or you can go the hard way and use plain Python/C API.

Community
  • 1
  • 1
MasterMind
  • 379
  • 2
  • 17