Wie erweitern Sie Python mit C ++?
Habe ich erfolgreich erweitert python mit C, Dank dieses handliche Skelett-Modul. Aber ich kann nicht finden, eine für C++, und ich habe die zirkuläre Abhängigkeit ärger, wenn Sie versuchen, um den Fehler zu beheben, dass C++ gibt, wenn ich kompilieren dieses Skelett Modul.
Wie Sie erweitern Python mit C++?
Ich würde eher nicht davon abhängen, erhöhen (oder SWIP oder andere Bibliotheken), wenn ich nicht muss. Abhängigkeiten sind ein Schmerz in den Hintern. Best-case-Szenario, finde ich einen skeleton-Datei, die bereits kompiliert mit C++.
Hier ist die bearbeitete Skelett, die ich gemacht habe für C++:
#include <Python.h>
#include "Flp.h"
static PyObject * ErrorObject;
typedef struct {
PyObject_HEAD
PyObject * x_attr; //attributes dictionary
} FlpObject;
static void Flp_dealloc(FlpObject * self);
static PyObject * Flp_getattr(FlpObject * self, char * name);
static int Flp_setattr(FlpObject * self, char * name, PyObject * v);
DL_EXPORT(void) initflp();
static PyTypeObject Flp_Type = {
/* The ob_type field must be initialized in the module init function
* to be portable to Windows without using C++. */
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Flp", /*tp_name*/
sizeof(FlpObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)Flp_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)Flp_getattr, /*tp_getattr*/
(setattrfunc)Flp_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
#define FlpObject_Check(v) ((v)->ob_type == &Flp_Type)
static FlpObject * newFlpObject(PyObject * arg)
{
FlpObject * self;
self = PyObject_NEW(FlpObject, &Flp_Type);
if (self == NULL)
return NULL;
self->x_attr = NULL;
return self;
}
//Flp methods
static void Flp_dealloc(FlpObject * self)
{
Py_XDECREF(self->x_attr);
PyMem_DEL(self);
}
static PyObject * Flp_demo(FlpObject * self, PyObject * args)
{
if (! PyArg_ParseTuple(args, ""))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef Flp_methods[] = {
{"demo", (PyCFunction)Flp_demo, 1},
{NULL, NULL} //sentinel
};
static PyObject * Flp_getattr(FlpObject * self, char * name)
{
if (self->x_attr != NULL) {
PyObject * v = PyDict_GetItemString(self->x_attr, name);
if (v != NULL) {
Py_INCREF(v);
return v;
}
}
return Py_FindMethod(Flp_methods, (PyObject *)self, name);
}
static int Flp_setattr(FlpObject * self, char * name, PyObject * v)
{
if (self->x_attr == NULL) {
self->x_attr = PyDict_New();
if (self->x_attr == NULL)
return -1;
}
if (v == NULL) {
int rv = PyDict_DelItemString(self->x_attr, name);
if (rv < 0)
PyErr_SetString(PyExc_AttributeError,
"delete non-existing Flp attribute");
return rv;
}
else
return PyDict_SetItemString(self->x_attr, name, v);
}
/* --------------------------------------------------------------------- */
/* Function of two integers returning integer */
static PyObject * flp_foo(PyObject * self, PyObject * args)
{
long i, j;
long res;
if (!PyArg_ParseTuple(args, "ll", &i, &j))
return NULL;
res = i+j; /* flpX Do something here */
return PyInt_FromLong(res);
}
/* Function of no arguments returning new Flp object */
static PyObject * flp_new(PyObject * self, PyObject * args)
{
FlpObject *rv;
if (!PyArg_ParseTuple(args, ""))
return NULL;
rv = newFlpObject(args);
if ( rv == NULL )
return NULL;
return (PyObject *)rv;
}
/* Example with subtle bug from extensions manual ("Thin Ice"). */
static PyObject * flp_bug(PyObject * self, PyObject * args)
{
PyObject *list, *item;
if (!PyArg_ParseTuple(args, "O", &list))
return NULL;
item = PyList_GetItem(list, 0);
/* Py_INCREF(item); */
PyList_SetItem(list, 1, PyInt_FromLong(0L));
PyObject_Print(item, stdout, 0);
printf("\n");
/* Py_DECREF(item); */
Py_INCREF(Py_None);
return Py_None;
}
/* Test bad format character */
static PyObject * flp_roj(PyObject * self, PyObject * args)
{
PyObject *a;
long b;
if (!PyArg_ParseTuple(args, "O#", &a, &b))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
/* List of functions defined in the module */
static PyMethodDef flp_methods[] = {
{"roj", flp_roj, 1},
{"foo", flp_foo, 1},
{"new", flp_new, 1},
{"bug", flp_bug, 1},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initflp) */
DL_EXPORT(void) initflp()
{
PyObject *m, *d;
/* Initialize the type of the new type object here; doing it here
* is required for portability to Windows without requiring C++. */
Flp_Type.ob_type = &PyType_Type;
/* Create the module and add the functions */
m = Py_InitModule("flp", flp_methods);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
ErrorObject = PyErr_NewException("flp.error", NULL, NULL);
PyDict_SetItemString(d, "error", ErrorObject);
}
Diese kompiliert Ordnung für mich, aber wenn ich es testen:
$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import flp
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dynamic module does not define init function (initflp)
>>>
extern "C"
. InformationsquelleAutor der Frage andrewrk | 2010-05-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erste von allen, obwohl Sie nicht wollen, um die Einführung eines zusätzlichen Abhängigkeit, empfehle ich Ihnen, einen Blick auf PyCXX. Zitieren von seiner Webseite:
Ich denke PyCXX ist lizenziert unter der BSD-Lizenz, was bedeutet, dass Sie können genauso gut auch die ganze source-code von PyCXX in der verteilten tarball von Ihrer Erweiterung, wenn Sie Ihre Erweiterung wird veröffentlicht unter einer ähnlichen Lizenz.
Wenn Sie wirklich und absolut nicht wollen, zu hängen, PyCXX oder andere third-party-Bibliothek, die ich denke, Sie müssen nur wrap Funktionen, die aufgerufen werden, indem Sie den Python-interpreter in
extern "C" {
und}
zu vermeiden, die name manglings.Hier der korrigierte code:
InformationsquelleAutor der Antwort Tamás
verwenden extern C wickeln alle Funktionsnamen, die aufgerufen werden, von python. Da C++ - Compiler verwenden, sowas nennt sich "name mangling' (notwendig für den Umgang mit überlastung), python kann nicht Lesen von c++ - Bibliotheken. Aber extern C wird Ihre Probleme zu lösen. Machen Sie es wie diese:
Zusätzliche stellen Sie sicher, dass Sie jedes python-Funktion muss in der extern-block. Sie können immer noch c++ - Funktionen in den Funktionen, es ist nur so, dass die Namen werden exportiert, ohne name mangling'.
InformationsquelleAutor der Antwort amwinter
Was Boost::Python?
EDIT: sorry, ich hab beaufsichtigen, dass Sie nicht wollen, zu hängen, boost, aber ich denke, es könnte immer noch eine der besten Optionen.
InformationsquelleAutor der Antwort MKroehnert