2015-02-03 13 views
7

파이썬 용 C 코드를 약간 감쌌다. C 모듈은 핸들을 만듭니다.이 핸들은 파이썬에 PyCapsule으로 전달됩니다. 필자가 원하는 API는 파이썬에서 다음과 같이 작성할 수 있습니다.C에서 Python 클래스 정의

import wrapped 

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

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

그래서 문제는 더 미적 문제입니다. 래퍼를 래핑해야합니까, 아니면 위의 코드를 C 코드로 옮길 수 있습니까? 즉, 여러 함수 대신 클래스를 내 보내면됩니까?

답변

0

귀하의 질문에 맞지 않을 수도 있습니다. 하지만 도움이 될 수 있습니다.

#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

예, 파이썬 형/클래스 유형에 맞는 적절한에 가득 PyTypeObject 구조의 인스턴스는 C API에서 C.에서 자신의 클래스 유형을 만들 수 있습니다. 이 작업을 수행하는 전체 절차는 다음 튜토리얼에 잘 설명되어 있습니다 :

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

이 초기 핵심 유형을 정의하고 유형/클래스에 데이터와 메소드를 추가하는 과정을 안내합니다. 처음에는 C로 구현 된 클래스를 얻는 데 엄청난 노력이 필요할 것 같지만 일단 몇 번 해보고 익숙해지면 정말 그렇게 나쁘지 않습니다.

다음은 질문에 정의한 Test 클래스의 기본 구현입니다.

#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); 
} 

그리고 파이썬 인터프리터에서의 사용 :

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