指向SWIG中C结构的python指针 – 访问struct成员

我正在尝试使用一个非常基本的Python-to-C接口与SWIG一起工作,我可以将一个指向结构的指针传递给一个C函数并且成员被填充,然后我可以访问python中的成员。

在下面的例子中,除了我尝试打印结构成员时,一切都有效:

print swig_test.diags_mem0_get(var) 

结果是:

 $ ./runpython.py Traceback (most recent call last): File "./runpython.py", line 11, in  print swig_test.diags_mem0_get(var) AttributeError: 'module' object has no attribute 'diags_mem0_get' 

鉴于此:

 print var.mem0 

结果是:

 $ ./runpython.py swig/python detected a memory leak of type 'uint16_t *', no destructor found. 

我正在关注SWIG 3.0文档,特别是“5.5结构和联合”部分: http : //swig.org/Doc3.0/SWIGDocumentation.html#SWIG_nn31

我究竟做错了什么?

我把这个例子简化为裸骨:

swig_test.h

 typedef struct diags_t { uint16_t mem0; uint16_t mem1; } diags; diags *malloc_diags(void); void free_diags(diags *pdiag); int get_diags(diags *pdiags); 

swig_test.c

 #include  // malloc() #include  // uint16_t #include "swig_test.h" int main(int argc, char **argv) { return 0; } int get_diags(diags *pdiags) { pdiags->mem0 = 0xdead; pdiags->mem1 = 0xbeef; return 0; } diags *malloc_diags(void) { diags *dptr = malloc(sizeof(diags)); return dptr; } void free_diags(diags *pdiag) { if (pdiag != NULL) free(pdiag); } 

swig_test.i

 %module swig_test %{ #include "swig_test.h" %} %include "swig_test.h" 

Makefile文件

 CXX = gcc INCLUDES = -I./ COMPFLAGS = -c -Wall -fPIC PYINC = /usr/include/python2.7 SWIG = /usr/bin/swig all: swig_test _swig_test.so swig_test: swig_test.o $(CXX) -Wall $^ -o $@ swig_test.o: swig_test.c $(CXX) $(COMPFLAGS) $(INCLUDES) $^ _swig_test.so: swig_test_wrap.o swig_test.o $(CXX) -shared $^ -L$(PYLIB) -lpython2.7 -o $@ swig_test_wrap.o: swig_test_wrap.c $(CXX) $(COMPFLAGS) $(INCLUDES) -I$(PYINC) $^ swig_test_wrap.c: swig_test.i $(SWIG) -python $(INCLUDES) $^ 

最后是简单的python示例:

runpython.py

 #!/usr/bin/python2 import swig_test var = swig_test.malloc_diags() if var == 'NULL': print "Error, no memory left" else: ret = swig_test.get_diags(var) if ret == 0: print swig_test.diags_mem0_get(var) print var.mem0 swig_test.free_diags(var) 

您正在寻找的function来自打字机。 文档自由承认“乍一看,这段代码看起来有点令人困惑。” 这对我有用。

从本质上讲,类型映射是SWIG在需要在Python和C之间进行转换时交换的几行代码。它们分别为Python到C( %typemap(in) )和C到Python( %typemap(out) )。 SWIG的文档还定义了一些神奇的变量:

$input是指需要转换为C / C ++的输入对象。

$result指的是一个由包装函数返回的对象。

$1指的是一个C / C ++变量,它与typemap声明中指定的类型相同(本例中为int)。

对于无符号整数支持,您只需要uint8_tuint16_tuint32_t输入和输出映射

下面的行提供了该function。 它们可以进入SWIG的.i文件或主标题( ifdef SWIG保护它们)。

 /* uintXX_t mapping: Python -> C */ %typemap(in) uint8_t { $1 = (uint8_t) PyInt_AsLong($input); } %typemap(in) uint16_t { $1 = (uint16_t) PyInt_AsLong($input); } %typemap(in) uint32_t { $1 = (uint32_t) PyInt_AsLong($input); } /* uintXX_t mapping: C -> Python */ %typemap(out) uint8_t { $result = PyInt_FromLong((long) $1); } %typemap(out) uint16_t { $result = PyInt_FromLong((long) $1); } %typemap(out) uint32_t { $result = PyInt_FromLong((long) $1); } 

我觉得有用的资源:

一个“修复”是将uint16_t成员更改为int类型。 然后这个语法有效:

 print var.mem0 

很明显,SWIG在非整数类型方面存在一些问题。

如果有人提出一个让我保留uint16_t类型的替代解决方案,我会喜欢它。