SWIG如何将缓冲区(char数组)和指针从C包装到Python?

时间:2013-02-20 21:20:51

标签: python c swig

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 个答案:

答案 0 :(得分:1)

问题是SWIG正在尝试将缓冲区包装为Python中的String,而不仅仅是指针。 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是迄今为止最干净的解决方案。