Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 809
Hailiang Zhang Avatar asked Jul 13 '15 19:07

Hailiang Zhang


People also ask

How does Python call C code?

cPython has two main ways to call C code: either by loading a shared library and calling its symbols, or by packing C code as Python binary modules and then calling them from Python code as though they were ordinary Python modules, which is how high performance stuff in the standard library is implemented - e.g. json.

What is needed for C extension?

In order to create a C-Extension, you must: Define the list of user functions in the C interface file, by including the fglExt. h header file. Compile the C interface file with your C compiler.

What is a Python extension?

Any code that you write using any compiled language like C, C++, or Java can be integrated or imported into another Python script. This code is considered as an "extension." A Python extension module is nothing more than a normal C library. On Unix machines, these libraries usually end in . so (for shared object).


2 Answers

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})
like image 108
Escualo Avatar answered Sep 18 '22 17:09

Escualo


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.

like image 27
Himanshu Mishra Avatar answered Sep 17 '22 17:09

Himanshu Mishra