在Python中如何使用返回结构体数组的C++函数?
我想在一个Python工具中使用一些现有的C++代码,具体是NvTriStrip库。
SWIG可以轻松处理一些简单参数的函数,但主要的函数GenerateStrips
就复杂得多了。
我需要在SWIG的接口文件中添加什么内容,以表明primGroups
实际上是一个输出参数,并且必须用delete[]
来清理呢?
///////////////////////////////////////////////////////////////////////////
// GenerateStrips()
//
// in_indices: input index list, the indices you would use to render
// in_numIndices: number of entries in in_indices
// primGroups: array of optimized/stripified PrimitiveGroups
// numGroups: number of groups returned
//
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
//
bool GenerateStrips( const unsigned short* in_indices,
const unsigned int in_numIndices,
PrimitiveGroup** primGroups,
unsigned short* numGroups,
bool validateEnabled = false );
顺便说一下,这里是PrimitiveGroup
的声明:
enum PrimType
{
PT_LIST,
PT_STRIP,
PT_FAN
};
struct PrimitiveGroup
{
PrimType type;
unsigned int numIndices;
unsigned short* indices;
PrimitiveGroup() : type(PT_STRIP), numIndices(0), indices(NULL) {}
~PrimitiveGroup()
{
if(indices)
delete[] indices;
indices = NULL;
}
};
3 个回答
我不知道怎么用SWIG来做,但你可以考虑换用一些更新的绑定系统,比如Pyrex或者Cython。
举个例子,Pyrex可以让你在某些情况下使用C++的删除操作。下面是文档中的一段摘录:
处理内存
可以对指向C++结构体的指针使用del语句来释放内存。这相当于C++中的delete。
cdef Shrubbery *big_sh big_sh = new Shrubbery(42.0) display_in_garden_show(big_sh) del big_sh
http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/version/Doc/Manual/using_with_c++.html
其实,直接为一些东西制作Python绑定是非常简单的,我真不明白为什么大家还要去折腾那些复杂的包装工具,比如SWIG。
只需要对外部数组的每个元素使用一次 Py_BuildValue,为每一行生成一个元组。然后把这些元组存储在一个C数组里。接着调用 PyList_New 和 PyList_SetSlice 来生成一个元组列表,最后从你的C函数返回这个列表的指针。
你有没有看过SWIG的文档,特别是关于他们的“cpointer.i”和“carray.i”库的部分?这些内容可以在这里找到。如果你不想自己创建一些工具库来配合你包装的代码,就得按照这些方法来操作。关于如何在Python中处理指针,你可以查看SWIG的相关链接。
接下来谈谈你关于如何区分输入和输出的问题。文档中还有一个部分这里,专门讲这个内容。你需要在*.i文件中标记为OUTPUT
。所以在你的情况下,你可以这样写:
%inline{
extern bool GenerateStrips( const unsigned short* in_dices,
const unsigned short* in_numIndices,
PrimitiveGroup** OUTPUT,
unsigned short* numGroups,
bool validated );
%}
这样你就能得到一个函数,它同时返回一个布尔值和一个PrimitiveGroup*
数组,作为一个元组。
这样说清楚了吗?