我的project使用SWIG在一个名为tensorflow.python.pywrap_tensorflow
的模块中自动为一组C ++函数和类型创建包装器。我想直接使用Python C API定义一个新类型,并将其添加到该模块。 (特别是,我想定义一个实现Python buffer protocol的新类型,以便我可以将本机缓冲区公开为memoryview
。)
我可以通过在.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 */,
};
%}
执行此操作后,我想通过调用PyModule_AddObject()
将类型对象添加到SWIG生成的模块,可能是在模块初始化块(%init %{ ... %}
)中。但是,我不知道在创建tensorflow.python.pywrap_tensorflow
模块的生成代码中,从Py_InitModule()
(或Python 3.x中的PyModule_Create()
)返回的值会给出什么名称。我已经能够在%init %{ ... %}
块中创建第二个模块,但如果可能的话,我更愿意将其添加到自动生成的模块中。
回答这两个问题都可以解决我的问题:
是否有SWIG宏用于访问初始化块中生成的模块对象(例如,通过扩展到相应PyObject*
的变量名称)?这个对象似乎存储在我生成的代码中名为m
的局部变量中,但我不知道在所有发行版中是否保证相同。
或者是否有更惯用的方法来实现我想要使用SWIG实现的目标?缓冲协议类型映射似乎来自他们的documentation似乎是为了编写接受缓冲区作为参数的函数而设计的,而我希望我的包装器类型实现缓冲区协议。
答案 0 :(得分:0)
如果您正在编写自己的类或结构,swig将为它构建一个python类型,您所要做的就是添加插槽。尝试%功能(python:slot)。此功能可以让您向生成的python类型插槽添加任意函数/结构。还可以使用&#39; -builtin&#39;来构建.i文件选项,发出不必要的代理python文件。
答案 1 :(得分:0)
只是让Jacky的答案更明确-您可能想要做类似的事情:
%{
static *PyBuffer mycoolbuffer_function(PyObject* self) {
// get the C data for self
// build your buffer
}
%}
%feature("python:tp_as_buffer") MyTypeThatWillBeWrapped "&mycoolbuffer_function";
这是未经测试的,我从迭代器所做的一些工作中进行了类比。当然,它需要-builtin选项。