Wrapping C++ code with python (manually)
Asked Answered
J

5

15

I have a main file(main.cpp) and a header file(nodes.hpp). The main file takes N(any positive integer) as input argument and by using the functions of header file it gives output say 'x & y' (both double).

Note:

  1. Both main and header files are written in C++.
  2. Both main and header files instead of using data structues as arrays,vectors, make use of Eigen Library.

I have to write a python wrapper for them, I have working knowledge of python but have never used any wrapper.

Can anybody please refer or give some notes about using python wrpper for such code?

Junoesque answered 13/4, 2017 at 8:26 Comment(2)
Maybe start by reading the documentation, which also mentions some 3rd party tools you could investigate.Paramorphism
One of the nicest and most modern libs would be pybind11 (which is getting more popular each day). Without much experience, this besides cython is the only one i tried and it worked great. Boost.Python is generally considered nice to use compared to the heavy-stuff like SWIG and co. but it's bounded by boost's build-tools. This is what pybind11 gets rid of if you are able to use a modern c++ compiler!Agentive
D
15

Here are your options:

  1. You can use ctypes, and I consider this the cleanest solution, because you convert your program to a shared library that can be called by any other software, not only Python. You, though, have to write a C-interface for your program yourself.

  2. You can use Python C-Extension, and I consider this the worst solution, because it's very low level, and prone to memory leaks, and costs lots of time to implement one function, and is Python-version dependent. Basically this is good to start a Python interpreter inside your C++. You can create PyObjects (which is the main building block of any Python type) and deal with them insdie C/C++.

  3. You can use pybind11 or pybind11k. These are C++ template driven and could be considered descendants of Boost.Python mentioned below.

  4. You can use SWIG, where it automatically creates the the interface that you have to create with ctypes through an interface file that you define. People say it's very good, but the documentation is not as good.

  5. You can use Boost.Python, which is good, but it has a very ugly build system with bjam. If you can manage to bypass that, then it's even better than ctypes. I'm a big boost fan, but bjam is why I don't use this.

What I do typically is ctypes. I trust it because it emphasizes the single-reponsibility principle. The library has a job that's separate from the interface (the C-interface), which is also separate from your Python script that uses that interface and exposes "the easy functionality" to the user.

Dola answered 13/4, 2017 at 9:26 Comment(0)
M
13

Use Boost.Python. Here is my tutorial, previously on SO Docs.


Using Boost.Python

Things are easy when you have to use a C++ library in a Python project. Just you can use Boost.

First of all here is a list of components you need:

  • A CMakeList.txt file, because you're going to use CMake.
  • The C++ files of the C++ project.
  • The python file - this is your python project.

Let's start with a small C++ file. Our C++ project has only one method which returns some string "This is the first try". Call it CppProject.cpp

char const *firstMethod() {
    return "This is the first try.";
}

BOOST_PYTHON_MODULE(CppProject) {
    boost::python::def("getTryString", firstMethod); // boost::python is the namespace
}

Have a CMakeLists.txt file a below:

cmake_minimum_required(VERSION 2.8.3)
FIND_PACKAGE(PythonInterp)
FIND_PACKAGE(PythonLibs)
FIND_PACKAGE(Boost COMPONENTS python)

INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})

PYTHON_ADD_MODULE(NativeLib CppProject)
FILE(COPY MyProject.py DESTINATION .) # See the whole tutorial to understand this line

By this part of the tutorial everything is so easy. you can import the library and call method in your python project. Call your python project MyProject.py.

import NativeLib
print (NativeLib.getTryString)

In order to run your project follow the instructions below:

  • Create a directory with the name build.
  • Enter into that directory.
  • Give the command cmake -DCMAKE_BUILD_TYPE=Release ..
  • make
  • python MyProject.py. Now, you have to see the string which the method in your C++ project returns.
Membrane answered 13/4, 2017 at 8:29 Comment(2)
missing #include boost/python.hppRunkle
Thank you very much Tuna. So does wrapping a C++ code is literally writing same functionality in Python or is literally running C++ in Python? Does that mean we need C++ compiler to run wrapped C++ code that in Python please?Compass
E
4

Edit: We point Google's open source C++ developers to pybind11 or our pybind11k fork of that these days.


Another tool for C++ wrapper generation is CLIF. Released in 2017, Google uses this for most everything these days. We no longer allow new SWIG wrappers to be written for Python internally.

It is built on top of Clang for the C++ parsing and requires relatively idiomatic modern C++ API use (unsurprisingly following Google's Style Guide) rather than any attempt to allow you to shoot yourself in the foot via SWIG's "support everything poorly" approach.

Eous answered 3/1, 2018 at 0:20 Comment(3)
2022 update: while we still use CLIF for most internal purposes, we're retooling that to work on top of pybind11 and simply point people to pybind11 for open source C++ wrapping work or when they need more than CLIF can provide.Eous
Hi, pybind11 is still SotA for this type of task?Berkeleianism
Yes, though Google has their own fork called pybind11k (linked above) to deal with a few issues. (Most people probably do not need the fork)Eous
F
2

See the official Python extending documentation.

this link will provide you simple example of how to include a cpp module and use it from the python interpreter, or if this is possible try with Cython: http://cython.org/

Cython will allow you to write C-like, Python-like code which will be translated to CPP compiled and then will be easily accessible from the Python.

Footman answered 13/4, 2017 at 8:28 Comment(0)
G
0

You can use Boost.Python

or go with the Python native interface

I would recommend Boost.Python if you already have Boost set up.

Gad answered 13/4, 2017 at 8:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.