2015-02-03 14 views
7

Zawinęłem kod C dla Pythona i to działa. Moduł C tworzy uchwyt, który przekazuję do Pythona jako PyCapsule. API, które chciałbym mieć, może być wykonane w języku Python, takim jak:Definiowanie klasy Python z C

import wrapped 

class Test(object): 
    def __init__(self, loc): 
     self.handle = wrapped.new(loc) 

    def foo(self, data): 
     return wrapped.foo(self.handle, data) 

Pytanie jest bardziej kosmetycznym problemem. Czy muszę owijać opakowanie, czy mogę przenieść kod jak pokazano powyżej do kodu C, tzn. Wyeksportować klasę zamiast zestawu funkcji?

Odpowiedz

0

Może to nie jest twoje pytanie. Ale może być pomocne.

#include "boost/python.hpp" 

using namespace boost::python; 

int main() 
{ 
    Py_Initialize(); 
    object pyFunPlxMsgWrapper = import("your_module").attr("PlxMsgWrapper"); 
    pyFunPlxMsgWrapper(2, "string", "data"); 
    return 0; 
} 
3

Tak, można tworzyć własne typy klas w C Z C API typu Python/klasa jest instancją struktury PyTypeObject wypełnione odpowiednio dla danego typu. Cała procedura jest opisana w ten sposób ładnie w poniższym poradniku:

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

ten poprowadzi cię poprzez określenie początkowego typu rdzeń, a następnie dodawanie danych i metod do typu/klasy. Na początku może się wydawać, że praca jest zaimplementowana w języku C, ale jeśli zrobisz to kilka razy i poczujesz się z tym komfortowo, to naprawdę nie jest tak źle.

Oto podstawowa implementacja klasy Test zdefiniowanej w pytaniu.

#include <Python.h> 
#include "structmember.h" 

typedef struct { 
    PyObject_HEAD 
    /* Your internal 'loc' data. */ 
    int loc; 
} Test; 

static void 
MyTest_dealloc(Test* self) 
{ 
    self->ob_type->tp_free((PyObject*)self); 
} 

static PyObject * 
Test_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 
{ 
    Test *self; 

    self = (Test *)type->tp_alloc(type, 0); 
    self->loc = 0; 

    return (PyObject *)self; 
} 

static int 
Test_init(Test *self, PyObject *args, PyObject *kwds) 
{ 
    if (! PyArg_ParseTuple(args, "i", &self->loc)) 
     return -1; 

    return 0; 
} 

static PyMemberDef Test_members[] = { 
    {"loc", T_INT, offsetof(Test, loc), 0, "mytestobj loc"}, 
    {NULL} /* Sentinel */ 
}; 

static PyObject * 
Test_foo(Test* self, PyObject *args) 
{ 
    int data; 
    PyObject *result; 

    if (! PyArg_ParseTuple(args, "i", &data)) { 
     return NULL; 
    } 

    /* We'll just return data + loc as our result. */ 
    result = Py_BuildValue("i", data + self->loc); 

    return result; 
} 
static PyMethodDef Test_methods[] = { 
    {"foo", (PyCFunction)Test_foo, METH_VARARGS, 
    "Return input parameter added to 'loc' argument from init.", 
    }, 
    {NULL} /* Sentinel */ 
}; 

static PyTypeObject mytest_MyTestType = { 
    PyObject_HEAD_INIT(NULL) 
    0,       /*ob_size*/ 
    "mytest.MyTest",    /*tp_name*/ 
    sizeof(Test), /*tp_basicsize*/ 
    0,       /*tp_itemsize*/ 
    (destructor)MyTest_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*/ 
    "MyTest objects",   /* tp_doc */ 
    0,       /* tp_traverse */ 
    0,       /* tp_clear */ 
    0,       /* tp_richcompare */ 
    0,       /* tp_weaklistoffset */ 
    0,       /* tp_iter */ 
    0,       /* tp_iternext */ 
    Test_methods,  /* tp_methods */ 
    Test_members,  /* tp_members */ 
    0,       /* tp_getset */ 
    0,       /* tp_base */ 
    0,       /* tp_dict */ 
    0,       /* tp_descr_get */ 
    0,       /* tp_descr_set */ 
    0,       /* tp_dictoffset */ 
    (initproc)Test_init,/* tp_init */ 
    0,       /* tp_alloc */ 
    Test_new,     /* tp_new */ 
}; 

static PyMethodDef mytest_methods[] = { 
    {NULL} /* Sentinel */ 
}; 

#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ 
#define PyMODINIT_FUNC void 
#endif 
PyMODINIT_FUNC 
initmytest(void) 
{ 
    PyObject* m; 

    if (PyType_Ready(&mytest_MyTestType) < 0) 
     return; 

    m = Py_InitModule3("mytest", mytest_methods, 
         "Example module that creates an extension type."); 

    Py_INCREF(&mytest_MyTestType); 
    PyModule_AddObject(m, "Test", (PyObject *)&mytest_MyTestType); 
} 

I jego użytkowanie od interpretera Pythona:

>>> from mytest import Test 
>>> t = Test(5) 
>>> t.foo(10) 
15