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 --

Community
  • 1
  • 1
Sandy
  • 233
  • 1
  • 2
  • 18
  • Use [Boost.Python](http://www.boost.org/doc/libs/1_59_0/libs/python/doc/). No, seriously. Also, this question as worded is far too broad. – Barry Aug 27 '15 at 21:38
  • @ Barry Could you please tell , How to call i C++ class methods from python – Sandy Aug 27 '15 at 21:46
  • The top-voted answer at your link shows precisely what you need. – user58697 Aug 27 '15 at 22:18
  • Could pls elaborate @ user58697 – Sandy Aug 27 '15 at 22:21
  • might help: http://docs.scipy.org/doc/scipy/reference/tutorial/weave.html – Setepenre Aug 27 '15 at 23:30
  • @Barry: Boost is not the solution for everything. It's very convenient and saves a lot of time but sometimes its totally fine when OPs asks explicitly for non-boost solutions - especially when he/she wants to know whats going on under the surface or want to keep the control. Some people like it when their lego set is not already assembled after unboxing. ;) – HelloWorld Aug 28 '15 at 00:25
  • @Sandy: Can you please give some more information? Does your Python run in an embedded environment or do you want to call the function from your so library? – HelloWorld Aug 28 '15 at 00:27
  • @HelloWorld, python is running in Linux environment and I want to call function shared object library. I just want to know how I can call C++ methods in python , is there anything wrap in C and call the methods in C. Any other straight forward way s der? – Sandy Aug 28 '15 at 06:24
  • if i run the @HelloWorld code in Linux with following compile 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 – Sandy Aug 28 '15 at 15:51
  • You seem to be asking the same question on lots of threads. And not even replying to comments asking for clarification in some. – davo36 Sep 11 '15 at 05:02

1 Answers1

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

HelloWorld
  • 2,392
  • 3
  • 31
  • 68
  • 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 – Sandy Aug 28 '15 at 15:47
  • 1
    In Eclipse you need to link against the Python library. – HelloWorld Aug 28 '15 at 17:24
  • 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 – Sandy Aug 28 '15 at 20:29
  • I like to create a C++ shared objects in eclipse and call the python from Linux environment – Sandy Aug 28 '15 at 20:31
  • 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. – HelloWorld Aug 29 '15 at 00:11
  • Feel free to accept the answer if this is the solution you were looking for (at least from the source base). – HelloWorld Aug 31 '15 at 01:45