Can python-C++ extension get a C++ object and call its member function?
Asked Answered
M

2

11

I am writing a python/C++ application, that will call methods in C++ extension from python.

Say my C++ has a class:

class A
{
    private:
        int _i;
    public:
        A(int i){_i=i;}
        int get_i(){return _i;}
}

A a=A();

It there anyway that python can get a object in C++ and call its member function, i.e.:

import cpp_extension
a=cpp_extension.A()
print a.get_i()

Any reference to general reading is also appreciated.

Markham answered 13/7, 2015 at 19:3 Comment(0)
F
10

Yes. You can create a Python C++ extension where your C++ objects will be visible from within Python as if they were built-in types.

There are two main ways to go about it.

1.Create the extension yourself following the documentation provided in the CPython API Documentation.

2.Create the extension using a tool such as boost::python or SWIG.

In my experience boost::python is the best way to go about it (it saves you an enormous amount of time, and the price you pay is that now you depend on boost).

For your example, the boost::python bindings could look as follows:

// foo.cpp
#include <boost/python.hpp>

class A {

 public:

  A(int i)
      : m_i{i} { }

  int get_i() const {
    return m_i;
  }
 private:
  // don't use names such as `_i`; those are reserved for the
  // implementation
  int m_i;
};

BOOST_PYTHON_MODULE(foo) {
  using namespace boost::python;

  class_<A>("A", init<int>())
      .def("get_i", &A::get_i, "This is the docstring for A::get_i")
      ;
}

Compile:

g++ -o foo.so foo.cpp -std=c++11 -fPIC -shared \
-Wall -Wextra `python2.7-config --includes --libs` \
-lboost_python

and run in Python:

>>> import foo
>>> a = foo.A(2)
>>> a.get_i()
2
>>> print a.get_i.__doc__

get_i( (A)arg1) -> int :
    This is the docstring for A::get_i

    C++ signature :
        int get_i(A {lvalue})
Frenchman answered 13/7, 2015 at 19:9 Comment(5)
Thanks! Can you give me an example of the first approach, which seems not apparent from the document how the C++ class can be accessed from Python.Markham
@HailiangZhang A much simpler approach will be writing a pyx file and using it with Cython.Dap
@Himanshu Mishra I understand, but I am looking for solution with least dependency.Markham
The "least" dependency will mean that you want to write the .c file yourself. Then checkout the docs for extending Python with C/C++ here. But I must say, that is one thing you'll not like to do again. Go ahead.Dap
Hi, your example is very intuitive, I am a Python programmer, and I write few C++ codes, but these days, I want to write my Python module with C++ and create a .so file so that I can speedup my original Python code. Do you think rewriting Python code with C++ and create a .so to be called from Python can gain a large speedup?Disoperation
D
5

Short Answer: Yes, of course. All you need is to wrap the C++ code with a Python wrapper.

Elaborated:

Suppose your C++ code is inside class_file.h. In the same directory, create a .pxd file with any name of your choice with the following content

cdef extern from "class_file.h":
    cdef cppclass A:
        int _i
        A(int)
        int get_i

This is the wrapper of the C++ file. That's all you have to do using Cython. Further you need to write a .pyx file and cimport your pxd file like a simple module. You also need to have a setup.py which will create a .so file which can be imported by Python as easily as any other python module.

Do visit http://docs.cython.org/src/tutorial/cython_tutorial.html for any more help. I hope you find Cython very easy and very light-based.

Dap answered 13/7, 2015 at 19:6 Comment(5)
I am looking for solution with least dependency.Markham
Do you think there is a quick solution without using Cython/booost_python?Markham
Cython is the quickest solution one can possibly imagine for wrapping. Checkout the docs for extending Python with C/C++ to realize that doing the work manually is not an easy task. Cython generates the .c wrapper file (>10K lines) for you automatically with just 10-15 lines of your code.Dap
You can avoid writing setup.py and pyx files. Cython has a built-in magic in ipython. See docs.cython.org/src/quickstart/…Dap
I know Cython well, but I am looking for solutions without that dependency.Markham

© 2022 - 2024 — McMap. All rights reserved.