SWIG如何将C中的缓冲区(字符数组)和指针包装到Python中?

1 投票
1 回答
1158 浏览
提问于 2025-04-17 16:33

Swig的手册对我来说有点难懂。我正在把我的C语言库封装成Python,这样我就可以在Python中测试我的C代码。现在我想知道如何在Python中访问C语言的指针地址,

typedef struct _buffer_t {
char buf[1024];
char *next_ptr;
} buffer_t;



void parse_buffer(buffer_t * buf_p) {
    buf_p -> next_ptr ++;
}

我想在C代码中做的事情如下:

buffer_t my_buf;
my_buf.next_ptr = my_buf.buf;
parse_buffer(&my_buf);
expect_equal(&(my_buf.buf)+1, my_buf.next_ptr);

我在Python中怎么做同样的事情呢?导入了SWIG封装的模块后,我在Python中得到了一个buffer_t类。

1 个回答

1

问题在于,SWIG 正在尝试将缓冲区当作字符串来处理,而字符串不仅仅是一个指针。对于 next_ptr 的赋值操作会分配内存并复制字符串,而不仅仅是指针的赋值。你可以通过几种方法来解决这个问题。

最简单的方法是使用 %extend 在 Python 中添加一个“重置缓冲区”的方法:

%extend {
  void resetPtr() {
    $self->next_ptr=$self->buf;
  }
}

然后你可以在 Python 中调用这个方法来完成你想要的赋值操作。

另外,如果你想强制将缓冲区当作普通指针来处理,你可以让 SWIG 将这两个成员都当作 void* 来处理,而不是 char*char[]。我原本希望这能像对每种类型使用 %apply 那样简单,但在我的测试中,这似乎对 memberin 和 memberout 并不奏效:

%apply void * { char *next };
%apply void * { char buf[ANY] };

鉴于 memberin/memberout 的类型映射对于让这个工作至关重要,我认为 %extend 是最干净的解决方案。

撰写回答