Использование нового типа в расширении Python C
Я написал код для определения нового типа в Python C extension (MyStatus). Я написал код C, чтобы определить распределение, освобождение и т. д., Как указано на этой странице .
Я смог скомпилировать модуль и использовать его из python.
Теперь я пытаюсь использовать этот новый тип в другом расширении Python C (TestStatus) Мое требование состоит в том, что мне нужно иметь только один. Я не хочу использовать 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 on Rhel 6.3
В MyStatus у меня есть 2 переменные
typedef struct {
PyObject_HEAD
int mStatus;
PyObject *mErrorString;
} MyStatus;
Мне нужно инициализировать то же самое из TestStatus.
1 ответ:
Расширение 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
.