python 指向 SWIG 中 C 结构的指针——访问结构成员
python pointer to C structure in SWIG -- accessing the struct members
我正在尝试获得一个非常基本的 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 <module>
print swig_test.diags_mem0_get(var)
AttributeError: 'module' object has no attribute 'diags_mem0_get'
而这个:
print var.mem0
结果:
$ ./runpython.py
<Swig Object of type 'uint16_t *' at 0x7f8261e15b40>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 <stdlib.h> // malloc()
#include <stdint.h> // 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"
生成文件
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)
一个"fix"是将uint16_t
个成员改为int
个类型。然后这个语法有效:
print var.mem0
显然 SWIG 在处理非整数类型时存在一些问题。
如果有人提出替代解决方案让我保留 uint16_t
类型,我会很高兴。
您正在寻找的功能来自类型映射。该文档坦率地承认“乍一看,这段代码看起来有点混乱”。这是对我有用的。
本质上,typemap 是 SWIG 在 Python 和 C 之间需要转换时交换的几行代码。它们是为 Python 到 C 单独定义的(%typemap(in)
) 和 C 到 Python (%typemap(out)
)。 SWIG 的文档还定义了一些魔法变量:
$input
refers to an input object that needs to be converted to C/C++.
$result
refers to an object that is going to be returned by a wrapper function.
</code> refers to a C/C++ variable that has the same type as specified in the typemap declaration (an int in this example).</p>
</blockquote>
<p>对于无符号整数支持,您只需要 <code>uint8_t
、uint16_t
和 uint32_t
的输入和输出映射
下面几行提供了该功能。他们可以进入 SWIG 的 .i 文件,或主要的 header(有 ifdef SWIG
守卫在他们身边)。
/* uintXX_t mapping: Python -> C */
%typemap(in) uint8_t {
= (uint8_t) PyInt_AsLong($input);
}
%typemap(in) uint16_t {
= (uint16_t) PyInt_AsLong($input);
}
%typemap(in) uint32_t {
= (uint32_t) PyInt_AsLong($input);
}
/* uintXX_t mapping: C -> Python */
%typemap(out) uint8_t {
$result = PyInt_FromLong((long) );
}
%typemap(out) uint16_t {
$result = PyInt_FromLong((long) );
}
%typemap(out) uint32_t {
$result = PyInt_FromLong((long) );
}
我发现有用的资源:
我正在尝试获得一个非常基本的 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 <module>
print swig_test.diags_mem0_get(var)
AttributeError: 'module' object has no attribute 'diags_mem0_get'
而这个:
print var.mem0
结果:
$ ./runpython.py
<Swig Object of type 'uint16_t *' at 0x7f8261e15b40>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 <stdlib.h> // malloc()
#include <stdint.h> // 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"
生成文件
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)
一个"fix"是将uint16_t
个成员改为int
个类型。然后这个语法有效:
print var.mem0
显然 SWIG 在处理非整数类型时存在一些问题。
如果有人提出替代解决方案让我保留 uint16_t
类型,我会很高兴。
您正在寻找的功能来自类型映射。该文档坦率地承认“乍一看,这段代码看起来有点混乱”。这是对我有用的。
本质上,typemap 是 SWIG 在 Python 和 C 之间需要转换时交换的几行代码。它们是为 Python 到 C 单独定义的(%typemap(in)
) 和 C 到 Python (%typemap(out)
)。 SWIG 的文档还定义了一些魔法变量:
$input
refers to an input object that needs to be converted to C/C++.
$result
refers to an object that is going to be returned by a wrapper function.的输入和输出映射
</code> refers to a C/C++ variable that has the same type as specified in the typemap declaration (an int in this example).</p> </blockquote> <p>对于无符号整数支持,您只需要 <code>uint8_t
、uint16_t
和uint32_t
下面几行提供了该功能。他们可以进入 SWIG 的 .i 文件,或主要的 header(有
ifdef SWIG
守卫在他们身边)。/* uintXX_t mapping: Python -> C */ %typemap(in) uint8_t { = (uint8_t) PyInt_AsLong($input); } %typemap(in) uint16_t { = (uint16_t) PyInt_AsLong($input); } %typemap(in) uint32_t { = (uint32_t) PyInt_AsLong($input); } /* uintXX_t mapping: C -> Python */ %typemap(out) uint8_t { $result = PyInt_FromLong((long) ); } %typemap(out) uint16_t { $result = PyInt_FromLong((long) ); } %typemap(out) uint32_t { $result = PyInt_FromLong((long) ); }
我发现有用的资源: