Wrap C++-Klasse (Wie bringt man Py. deren Methoden bei?)

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
zippy84
User
Beiträge: 2
Registriert: Mittwoch 1. Juni 2011, 15:18

Hallo,

bin gerade dabei mich in die C-API von Python einzuarbeiten. Ich möchte einen eigenen Typ erstellen, der aus einer vorhandenen C++-Klasse enstehen soll. Ich hab mir den Part mit den dem struct in der Dokumentation von Python 2.7 durchgelesen, weiß aber nicht so recht wie ich das auf eine Klasse anwenden soll. Besonders bei den nicht statischen Methoden der Klasse komme ich nicht weiter. Wie gibt man diese bei tp_methods im PyTypeObject an?

Könnte mir das bitte jemand von euch am nachstehenden Beispiel zeigen?

Code: Alles auswählen

#include <vector>

struct Pt { double x, y; };

class Test {
public:
  std::vector<Pt> pts;
  
  unsigned int addPt(double x, double y) {
    Pt pt;
    pt.x = x;
    pt.y = y;
    
    pts.push_back(pt);
  }
  
};

/*
 * im python hätte ichs gern so:
 * import Test
 * a = Test.Test()
 * a.add_pt(3.7, 2.9)
 * */
Zuletzt geändert von zippy84 am Donnerstag 2. Juni 2011, 19:03, insgesamt 1-mal geändert.
deets

@zippy84

Ich wuerde dir empfehlen, statt von Hand zu wrappen einen der verfuegbaren Generatoren zu verwenden. Ich persoenlich bevorzuge SIP bzw. in letzter Zeit habe ich auch mit Cython gute Erfahrungen gemacht. Das vereinfacht dir die Sache *sehr*.
zippy84
User
Beiträge: 2
Registriert: Mittwoch 1. Juni 2011, 15:18

Ich habe mich nun mal an einem konkreteren Beispiel beschäftigt. Das hier ist dabei herausgekommen:

Code: Alles auswählen

#include <Python.h>
#include <vector>

struct Pt { double x, y; };

class PNL {
public:
  typedef std::vector<Pt> PolyType;
  std::vector<PolyType> polys;
  
  void addPoly(PolyType poly);
 
};

void PNL::addPoly(PolyType poly) {
  polys.push_back(poly);
}

static PyObject* add_poly(PNL *self, PyObject *args) {
  PyObject *ptsList;
  
  if(PyArg_ParseTuple(args, "O", &ptsList) < 0)
    return NULL;
  
  int ptNbr = PySequence_Length(ptsList);
  
  PNL::PolyType poly;
  
  for(unsigned int i = 0; i < ptNbr; i++) {
    PyObject *pt = PySequence_GetItem(ptsList, i);
    
    PyObject *x = PyTuple_GetItem(pt, 0);
    PyObject *y = PyTuple_GetItem(pt, 1);
    
    Pt point;
    point.x = PyFloat_AsDouble(x);
    point.y = PyFloat_AsDouble(y);
    
    poly.push_back(point);
    
  }
  
  self->addPoly(poly);
  
  Py_INCREF(Py_None);
  return Py_None;
}

static PyMethodDef PNLPyType_methods[] = {
  {"add_poly", (PyCFunction) add_poly, METH_VARARGS, "Adds a polygon."},
  {NULL}
};

static PyTypeObject PNLPyType = {
  PyObject_HEAD_INIT(NULL)
  0,
  "pnl.PNL",
  sizeof(PNL)
};

static PyMethodDef pnl_module_methods[] = {
  {NULL}
};

PyMODINIT_FUNC initpnl() {
  PNLPyType.tp_new = PyType_GenericNew;
  PNLPyType.tp_methods = PNLPyType_methods;
  PNLPyType.tp_doc = "The PNL type.";
  PNLPyType.tp_flags = Py_TPFLAGS_DEFAULT; 
  
  if(PyType_Ready(&PNLPyType) < 0)
    return;
  
  PyObject* pnl = Py_InitModule("pnl", pnl_module_methods);
  
  Py_INCREF(&PNLPyType);
  PyModule_AddObject(pnl, "PNL", (PyObject*) &PNLPyType);
}


int main(int argc, char *argv[]) {
  Py_SetProgramName(argv[0]);
  Py_Initialize();
  initpnl();
}
Ich kann es in Python importieren, jedoch erhalte ich ein Segmentation fault, wenn ich folgende ausführe:

Code: Alles auswählen

>>> a = pnl.PNL()
>>> a.add_poly(((7, 1), (2, 3)))
Irgendwas scheine ich vergessen zu haben, nur was?
Antworten