Этот ответ является только Python2.x!
Если вы хотите написать C++ - расширение, сначала необходимо загрузить python-dev
пакет, чтобы получить все необходимые LIBS и файлы заголовков (нужен только на Linux)
Самая важная часть в следующем источнике это PolygonObject
и PyTypeObject
.
PolygonObject
Объект этого класса представляет собой экземпляр Polygon в Python. Как видите, он содержит указатель 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);
}
лязг ++ -shared -I/USR/включать/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
Используйте [Boost.Python] (http://www.boost.org/doc/libs/1_59_0/libs/python/doc/). Нет, серьезно. Кроме того, этот вопрос сформулирован слишком широко. – Barry
@ Barry Не могли бы вы рассказать, как вызвать методы класса C++ из python? – Sandy
Ответ на верхний голос по вашей ссылке показывает именно то, что вам нужно. – user58697