2013-11-22 2 views
2

Я написал код для определения нового типа в расширении Python C (MyStatus). Я написал код C, чтобы определить распределение, освобождение и т. Д., Как указано в этом page.Использование нового типа в Python C Extension

Я смог скомпилировать модуль и использовать его с python.

Теперь я пытаюсь использовать этот новый тип в другом расширении Python C (TestStatus) . Мое требование - мне нужно иметь только один .so для этого. Я не хочу использовать MyStatus непосредственно из кода Python. Я буду импортировать TestStatus в свой код, и я хочу инициализировать MyStatus из моего расширения C, написанного для TestStatus.

Я написал код, как это для TestStatus

static PyObject * TestStatus_checkPyObject *self, PyObject *args) 
{ 
    PyObject * mystatus = NULL; 
    const char *command; 

    /* Call the class object. */ 
    mystatus = PyObject_CallObject((PyObject *) &MyStatusType, NULL); 

    return mystatus; 
} 

    PyMODINIT_FUNC initTestStatus(void) 
    { 
     (void) Py_InitModule("TestStatus", TestMethods); 

     initMyStatus();//This is available in the C code written for MyStatus 
    } 

Я был в состоянии создать так как то, что я уже упоминал в коде. Но я застрял на настройке переменных для MyStatus, который является целым числом, и char * (PyObject *) Может кто-то пролить свет на это, например, правильно ли мой подход и как инициализировать и использовать MyStatus из TestStatus с аргументами.

Я пытаюсь это с Python 2.6.6 на RHEL 6.3

В MyStatus у меня есть 2 переменные

typedef struct { 
    PyObject_HEAD 
    int   mStatus; 
    PyObject *mErrorString; 
} MyStatus; 

мне нужно инициализировать то же самое от TestStatus.

+0

Вы застряли в настройке «переменных», какие переменные? вы можете быть более конкретным, что поможет. Почему требуется иметь только файл '.so'? Будет ли это работать, если вы поместите код обоих модулей в один файл? - Извините, но я не бросил проблему, так что трудно пролить свет на нее. – dastrobu

+0

Я редактировал сообщение, чтобы добавить информацию об переменных. – Raghuram

ответ

2

Расширение Python C должно содержать C-API для использования с другими модулями C. Так что в вашем случае соу должны иметь что-то в вашем MyStatus.h как

/* Header file for MyStatus module */ 

#ifndef MyStatus_MODULE_H 
#define MyStatus_MODULE_H 
#ifdef __cplusplus 
extern "C" { 
#endif 

typedef struct { 
    PyObject_HEAD 
    int   mStatus; 
    PyObject *mErrorString; 
} MyStatus; 

#define MyStatus_Type_NUM 0 

#define MyStatus_New_NUM 1 
#define MyStatus_New_RETURN MyStatus * 
#define MyStatus_New_PROTO (int mStatus, PyObject *mErrorString) 

/* Total number of C API pointers */ 
#define MyStatus_API_pointers 2 

#ifdef MyStatus_MODULE 
/* do nothing for this minimal example */ 
#else 

static void **MyStatus_API; 

#define MyStatus_Type (*(PyTypeObject *)(\ 
    MyStatus_API[MyStatus_Type_NUM])) 

#define MyStatus_New \ 
(*(MyStatus_New_RETURN (*)MyStatus_New_PROTO) \ 
    MyStatus_API[MyStatus_New_NUM]) 

static int import_MyStatus(void) 
{ 
    MyStatus_API = (void **)PyCapsule_Import("MyStatus._C_API", 0); 
    return (MyStatus_API != NULL) ? 0 : -1; 
} 
#endif /* !defined(MyStatus_MODULE) */ 
#ifdef __cplusplus 
} 
#endif 
#endif /* !defined(MyStatus_MODULE_H) */ 

и определить что-то вроде

static Py MyStatus * 
PyMyStatus_New(int mStatus, PyObject *mErrorString){ 
    MyStatus *self; 
    self = (MyStatus *)MyStatusType.tp_alloc(&MyStatusType, 0); 
    self->mStatus = mStatus; 
    Py_INCREF(mErrorString); // in case you don't want to steal a reference 
    self->mErrorString = mErrorString; 
    if (!self->mErrorString){ 
     Py_DECREF(self); 
     return NULL; 
    } 
    return self; 
} 

#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ 
#define PyMODINIT_FUNC void 
#endif PyMODINIT_FUNC initMyStatus(void){ 
    PyObject *m = Py_InitModule3("MyStatus", methods, ""); 
    static void *MyStatus_API[MyStatus_API_pointers]; 

    MyStatus_API[MyStatus_Type_NUM] = (void *)&MyStatusType; 
    MyStatus_API[MyStatus_New_NUM] = (void *)MyStatus_New; 

    PyObject *c_api_object = PyCapsule_New((void *)MyStatus_API, "MyStatus._C_API", NULL); 
    if (c_api_object != NULL) PyModule_AddObject(m, "_C_API", c_api_object); } 

в MyStauts.c. Кроме того, это очень удобно определять макросы, как

PyMyStatus_SET_MSTATUS(self, mStatus) 
PyMyStatus_GET_MSTATUS(self) 
PyMyStatus_SET_mErrorString(self, mErrorString) 
PyMyStatus_GET_mErrorString(self) 

, чтобы иметь возможность изменить базовую структуру MyStatus позже и обрабатывать количество ссылок.

Если вы не хотите этого делать, вы можете всегда инициализировать и изменять объекты MyStatus, как показано в верхнем примере для функции MyStatus_New.

В TestStatus.c окончательно импортировать C-API.

PyMODINIT_FUNC initTestStatus(void){ 
    import_MyStatus(); 
    Py_InitModule3("TestStatus", methods, ""); 

} 

Теперь вы сможете использовать MyStatus_New и MyStatusType.

+0

У меня этот код как часть MyStatus. Но я сомневаюсь, как я могу назвать это с TestStatus. Как вы видите, я вызываю initMyStatus. Но в методах TestStatus я должен инициализировать объект MyStatus, инициализируя его ошибкой и статусом. То, где я застрял – Raghuram

+0

Я вижу. Я думаю, проблема заключается в том, что вы пытаетесь вызвать 'initMyStatus();' в 'initTestStatus'. Вам нужно вызвать 'import_MyStatus();' который вы должны определить в модуле 'MyStatus', чтобы импортировать C-API. Затем вы можете вызывать функции из «MyStatus» в «TestStatus» и использовать этот тип, если вы экспортировали его через C-API. – dastrobu

+0

См. Обновление моего ответа. – dastrobu

Смежные вопросы