0

I stuck with some problem in calling C++ methods in python I got this following link in stack overflow

But I don't to use Boost package and swig. Is there any approach in python can used to call these C++ methods. I am compiling C++ as a shared object in Linux and using in Python 2.7

#include <iostream>
using namespace std;

class Polygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
};

class Rectangle: public Polygon {
  public:
    int area()
      { return width*height; }
};

class Triangle: public Polygon {
  public:
    int area()
      { return width*height/2; }
};

int main () {
  Rectangle rect;
  Triangle trgl;
  Polygon * ppoly1 = &rect;
  Polygon * ppoly2 = &trgl;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  cout << rect.area() << '\n';
  cout << trgl.area() << '\n';
  return 0;
}

Could please guide to achieve this. Any code snippet or example will be highly appreciated.

Thanks in advance --

10
  • Use Boost.Python. No, seriously. Also, this question as worded is far too broad. Commented Aug 27, 2015 at 21:38
  • @ Barry Could you please tell , How to call i C++ class methods from python Commented Aug 27, 2015 at 21:46
  • The top-voted answer at your link shows precisely what you need. Commented Aug 27, 2015 at 22:18
  • Could pls elaborate @ user58697 Commented Aug 27, 2015 at 22:21
  • might help: docs.scipy.org/doc/scipy/reference/tutorial/weave.html Commented Aug 27, 2015 at 23:30

1 Answer 1

1

This answer is for Python2.x only!

When you want to write a C++-extension, you first need to download the python-dev package to get all the needed libs and header files (only needed on Linux)

The most important part in the following source is PolygonObject and PyTypeObject.

PolygonObject

An object of this class represents your Polygon instance in Python. As you can see it contains a pointer obj which is your original object.

PyTypeObject

https://docs.python.org/2/c-api/type.html#c.PyTypeObject

The C structure of the objects used to describe built-in types.

Here is how you can use your Polygon object:

import libfoo
po = libfoo.Polygon()
po.set_values(1, 2)

Here is the module implementation (libfoo.cpp). This example does not contain inheritance but the keyword you have to look for is tp_base. Also the original Python source has a lot of examples which can help here a lot.

#include <Python.h>

// this is your original class
class Polygon {
protected:
  int width, height;
public:
  void set_values (int a, int b)
  { width=a; height=b; }
};

typedef struct {
  PyObject_HEAD
  Polygon* obj;
} PolygonObject;

static void
Polygon_dealloc(PolygonObject* self)
{
  delete self->obj;
  self->ob_type->tp_free((PyObject*)self);
}

static PyObject *
Polygon_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  PolygonObject *self;

  self = (PolygonObject*)type->tp_alloc(type, 0);
  if (self != NULL) {
    self->obj = new Polygon;
    // do your cleanup here
  }

  return (PyObject *)self;
}

static PyObject* Polygon_set_values(PolygonObject* self, PyObject *args, PyObject *kwds)
{
  int a, b;
  const char* kwlist[] = {"a", "b", NULL};

  if (! PyArg_ParseTupleAndKeywords(args, kwds, "ii", (char**)kwlist, &a, &b))
    return NULL;

  self->obj->set_values(a, b);
  Py_INCREF(Py_None);
  return Py_None;
}

static PyMethodDef Polygon_methods[] = {
  {"set_values", (PyCFunction)Polygon_set_values, METH_VARARGS, "set the value"},
  {NULL}  /* Sentinel */
};

static PyTypeObject PolygonType = {
  PyObject_HEAD_INIT(NULL)
  0,                         /*ob_size*/
  "mod.Polygon",             /*tp_name*/
  sizeof(PolygonObject),           /*tp_basicsize*/
  0,                         /*tp_itemsize*/
  (destructor)Polygon_dealloc, /*tp_dealloc*/
  0,                         /*tp_print*/
  0,                         /*tp_getattr*/
  0,                         /*tp_setattr*/
  0,                         /*tp_compare*/
  0,                         /*tp_repr*/
  0,                         /*tp_as_number*/
  0,                         /*tp_as_sequence*/
  0,                         /*tp_as_mapping*/
  0,                         /*tp_hash */
  0,                         /*tp_call*/
  0,                         /*tp_str*/
  0,                         /*tp_getattro*/
  0,                         /*tp_setattro*/
  0,                         /*tp_as_buffer*/
  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
  "Polygon class",           /* tp_doc */
  0,                         /* tp_traverse */
  0,                         /* tp_clear */
  0,                         /* tp_richcompare */
  0,                         /* tp_weaklistoffset */
  0,                         /* tp_iter */
  0,                         /* tp_iternext */
  Polygon_methods,           /* tp_methods */
  0,                         /* tp_members */
  0,                         /* tp_getset */
  0,                         /* tp_base */
  0,                         /* tp_dict */
  0,                         /* tp_descr_get */
  0,                         /* tp_descr_set */
  0,                         /* tp_dictoffset */
  0,                         /* tp_init */
  0,                         /* tp_alloc */
  Polygon_new,               /* tp_new */
};

static PyMethodDef module_methods[] = {
  {NULL}  /* Sentinel */
};

PyMODINIT_FUNC
initlibfoo()
{
  PyObject* m;

  if (PyType_Ready(&PolygonType) < 0)
    return;

  m = Py_InitModule3("libfoo", module_methods, "Example module that creates an extension type.");
  if (m == NULL)
    return;

  Py_INCREF(&PolygonType);
  PyModule_AddObject(m, "Polygon", (PyObject *)&PolygonType);
}

clang++ -shared -I/usr/include/python2.7/ -fPIC libfoo.cpp -o libfoo.so -lpython

Here are two additional links which give you more information and a deeper technical background how to extend Python.

https://docs.python.org/2/extending/newtypes.html https://docs.python.org/2/extending/extending.html

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks alot, if i run the code in Linux with following option, it will work. But my project is eclipse, but i am not able to build this in eclipse. Getting undefined symbol error. Do you any idea regarding this? could you please help
In Eclipse you need to link against the Python library.
could you pls how to link the python library in eclipse, any snapshot will be highly appreciated. I am not familiar with eclipse environment, Thanks in advance
I like to create a C++ shared objects in eclipse and call the python from Linux environment
I have to pass on that one, not very familiar with Eclipse either. But this is also a different question. Feel free to open a new one.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.