指向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_t
, uint16_t
和uint32_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
类型的替代解决方案,我会喜欢它。