My project использует SWIG для автоматического создания оберток для набора функций и типов C++ в одном модуле, который называется tensorflow.python.pywrap_tensorflow
. Я хочу напрямую определить новый тип, используя API Python C, и добавить его в этот модуль. (В частности, я хочу, чтобы определить новый тип, который реализует Python buffer protocol, так что я могу выставить родной буфер как memoryview
.)SWIG и Python: Как добавить созданный вручную класс в SWIG-модуль?
я могу определить необходимые структур для моего нового типа, встраивания его в .i
файле :
%{
typedef struct {
PyObject_HEAD
/* Other fields... */
} MyType;
// Define functions for the initializer, destructor, and buffer protocol:
// * MyType_init
// * MyType_dealloc
// * MyType_old_getbuffer (the readbufferproc for Python 2.7)
// * MyType_segcount (for Python 2.7)
// * MyType_getbuffer (the Python 2.7/3.x buffer protocol)
// ...
static PyBufferProcs MyType_as_buffer = {
#if PY_VERSION_HEX < 0x03000000
(readbufferproc)MyType_old_getbuffer,
(writebufferproc)0,
(segcountproc)MyType_segcount,
(charbufferproc)0,
#endif
(getbufferproc)MyType_getbuffer,
(releasebufferproc)0,
};
static PyTypeObject MyType_TypeObject = {
/* PyObject header changed in Python 3 */
#if PY_VERSION_HEX>=0x03000000
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(NULL)
0 /* ob_size */,
#endif
"MyType" /* tp_name */,
sizeof(MyType) /* tp_basicsize */,
0 /* tp_itemsize */,
(destructor)MyType_dealloc /* tp_dealloc */,
0 /* tp_print */,
0 /* tp_getattr */,
0 /* tp_setattr */,
#if PY_VERSION_HEX>=0x03000000
0 /* tp_reserved in 3.0.1 */
#else
0 /* tp_compare */,
#endif
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 */,
&MyType_as_buffer /* tp_as_buffer */,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_NEWBUFFER /* tp_flags */,
"Python wrapper for MyType." /* tp_doc */,
0 /* tp_traverse */,
0 /* tp_clear */,
0 /* tp_richcompare */,
0 /* tp_weaklistoffset */,
0 /* tp_iter */,
0 /* tp_iternext */,
0 /* tp_methods */,
0 /* tp_members */,
0 /* tp_getset */,
0 /* tp_base */,
0 /* tp_dict */,
0 /* tp_descr_get */,
0 /* tp_descr_set */,
0 /* tp_dictoffset */,
(initproc)MyType_init /* tp_init */,
};
%}
После этого, я хочу, чтобы добавить объект типа к модулю SWIG сгенерированных путем вызова PyModule_AddObject()
, предположительно, в блоке инициализации модуля (%init %{ ... %}
). Однако я не знаю, какое имя следует указать для значения, возвращаемого с Py_InitModule()
(или PyModule_Create()
в Python 3.x) в сгенерированном коде, который создает модуль tensorflow.python.pywrap_tensorflow
. Мне удалось создать второй модуль в блоке %init %{ ... %}
, но я предпочел бы добавить его в автоматически сгенерированный модуль, если это возможно.
Ответ на любой из этих вопросов позволит решить мою проблему:
Есть ли SWIG макрос для доступа сгенерированного объекта модуля в блоке инициализации (например, путем расширения к имени переменному для соответствующего
PyObject*
)? Кажется, что этот объект хранится в локальной переменной с именемm
в моем сгенерированном коде, но я не знаю, гарантировано ли это во всех дистрибутивах.Или есть более идиоматический способ сделать то, что я пытаюсь достичь с помощью SWIG? Буквенные протоколы typemaps выглядят с их documentation, казалось, предназначены для написания функций, которые принимают буферы в качестве аргументов, тогда как я хочу, чтобы мой тип-оболочка реализовал буферный протокол.