Использование нового типа в расширении 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 2

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.