Search code examples
pythonc++dlldllexport

Export of C++ classes for Python


I have a program written in C++ (as a static library for now) with very abstract interface that uses operator overloading on my classes etc. I want to create a shared library out of it (DLL on Windows would be the first step, before trying other platforms) to use it in other more "user friendly" languages. I read that Python has some level of support for this with its ctypes.

I just want to know, if it is possible to use some higher level abstractions from a C++ DLL in Python to choose the right option before I invest time in trying to do something, that's impossible. User should be able to initialize the classes provided by my program and use them with all their methods including overloaded operators (only those available in python of course). Or is Python only meant to support some simple function calls etc.?

The C++ code (even just the user accessible classes) is huge and I would like to avoid creating separate Python wrappers, as all of the needed functionality is already done in C++.


Solution

  • Since no one answered, I will provide everything I have gathered myself in the meantime. Hope it might be helpful for some.

    Python's ctypes are meant to support only C language features. So there is no way to directly access classes and other C++ objects from Python using ctypes. However, there are some ways to access them.

    The tedious method

    Create C style objects for the C++ classes, and then create Python wrappers for them.

    The C style object would basically be a pointer to the C++ object allocated dynamically. It should have additional methods like for example the conventionally named ->Release() to destroy the object and free the allocated memory. Then you would need to create python wrappers manually that would resemble the original C++ object including the overloaded operators etc. (Sidenote: The only operator I came across, that could be needed in such situations and is not overloadable in Python is the assignment operator.)

    This is probably the best solution when you want to have full control over what's happening and don't mind duplicating the interface in Python.

    The quick method

    Boost provides a Boost::Python library to handle this. It lets you export practically anything you would need - classes, operators, even multiple overloaded methods.

    The only problem is, that this library is quite large and it's one of the non-header-only Boost libraries, so you would need to figure out how to build it with your project and this might not be easy for people, who never worked with Boost (like myself).

    I don't know what exactly this library does, maybe it just automates the same thing described in the previous method. So I'm not sure whether it reduces levels of additional wrappers or just simply does all the hard wrapping work for you, but it does what I needed to be done.

    The quicker method

    Luckily I came across an alternative - pybind11. It's a relatively small library, that does the same thing as Boost::Python and it's header-only. It has nice documentation and is easy to use. It's called pybind11 as it was originally meant to support C++11, but it currently supports C++14 and experimentally C++17, but I used it with a C++17 project and found no problems so far.

    I'm not yet sure which method would be the best for my project but for now, I use pybind11, just to make it easier while the project is under development.