从python调用C ++方法

时间:2015-08-27 21:29:49

标签: python c++ python-2.7 shared-objects

我在python I got this following link in stack overflow

中调用C ++方法遇到了一些问题

但我不会使用Boost包和swig。有没有python中的方法可以用来调用这些C ++方法。我正在编译C ++作为Linux中的共享对象并在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;
}

请指导实现这一目标。任何代码段或示例都将受到高度赞赏。

提前致谢 -

1 个答案:

答案 0 :(得分:1)

这个答案仅适用于Python2.x!

当你想编写C ++扩展时,首先需要下载python-dev包以获取所有需要的库和头文件(仅在Linux上需要)

以下来源中最重要的部分是PolygonObjectPyTypeObject

<强> PolygonObject

此类的对象表示Python中的Polygon实例。如您所见,它包含一个指针obj,它是您的原始对象。

<强> PyTypeObject

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

  

用于描述内置类型的对象的C结构。

以下是使用Polygon对象的方法:

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

以下是模块实现(libfoo.cpp)。此示例不包含继承,但您必须查找的关键字是tp_base。最初的Python源代码也有很多例子可以帮到很多。

#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

这里有两个额外的链接,可以为您提供更多信息以及如何扩展Python的更深入的技术背景。

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