在Python中如何使用返回结构体数组的C++函数?

6 投票
3 回答
820 浏览
提问于 2025-04-15 23:05

我想在一个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 个回答

1

我不知道怎么用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

2

其实,直接为一些东西制作Python绑定是非常简单的,我真不明白为什么大家还要去折腾那些复杂的包装工具,比如SWIG。

只需要对外部数组的每个元素使用一次 Py_BuildValue,为每一行生成一个元组。然后把这些元组存储在一个C数组里。接着调用 PyList_NewPyList_SetSlice 来生成一个元组列表,最后从你的C函数返回这个列表的指针。

2

你有没有看过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*数组,作为一个元组。

这样说清楚了吗?

撰写回答