在SWIG for Python中创建时如何初始化C结构成员?

问题描述

假设我们在C中具有以下结构:

typedef struct buffer
{
    uint8_t* const data;
    const size_t maxSize;
    size_t size;
} buffer_t;

如何为此做一个SWIG包装器,以便在Python中创建buffer_t时,它为数据指针分配给定的字节数并相应地设置maxSize?

详细信息

因此,基本上,这里的问题与常量结构成员有关。认情况下,SWIG使用认值初始化结构。这会导致问题:

StructWithConsts_t struct;
struct.constant = 5; // Error. This should've been set when creating the struct.

构造函数和析构函数的公认答案为该问题提供了解决方案。

解决方法

您可以在SWIG中将C结构视为C ++类,并使用creator和destroyers方法对其进行扩展。

在您的情况下,您的.i应该有这个

typedef struct
{
    uint8_t* const data;
    const size_t maxSize;
    size_t size;
} buffer_t;

%extend buffer_t {
    buffer_t(size_t size)
    {
        buffer_t* pBuffer = malloc(sizeof *pBuffer);
        pBuffer->data = malloc(size * sizeof (*pBuffer->data));
        pBuffer->maxSize = size;
        return pBuffer;
    }

    void ~buffer_t()
    {
        buffer_t *pBuffer = ($self);
        free(pBuffer->data);
        free(pBuffer);
        return;
    }
};

在python中,它将像这样使用

from yourmodule import buffer_t

buffer = buffer_t(10)

垃圾收集器将负责释放内存。

还有其他方法可以执行此操作,但是您没有可复制的示例来进行测试。

,

我找到了一个解决方案,但是由于指针类型转换,它有点黑。我不认为这是执行此操作的正确方法,但是它可以起作用:

在.i文件中,我使用%inline创建了一个包装器:

%inline %{
buffer_t* new_buffer(size_t size)
{
    buffer_t* pBuffer = (buffer_t*)malloc(sizeof(buffer_t));
    *(uint8_t**)&pBuffer->data = (uint8_t*)malloc(size * sizeof(uint8_t));
    *(size_t*)&pBuffer->maxSize = size;
    return (buffer_t*)pBuffer;
}

void free_buffer(buffer_t* pBuffer)
{
    free(pBuffer->data);
    free(pBuffer);
    return;
}
%}