首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指向C结构的python指针--访问结构成员

指向C结构的python指针--访问结构成员
EN

Stack Overflow用户
提问于 2016-02-23 18:34:48
回答 2查看 2.3K关注 0票数 0

我正在尝试获得一个非常基本的python接口,在该接口中,我可以传递一个指向C函数的结构的指针,然后成员被填充,然后我可以访问python中的成员。

在下面的示例中,除了尝试打印结构成员之外,一切都正常:

代码语言:javascript
复制
print swig_test.diags_mem0_get(var)

在以下方面的成果:

代码语言:javascript
复制
$ ./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'

鉴于这一点:

代码语言:javascript
复制
print var.mem0

在以下方面的成果:

代码语言:javascript
复制
$ ./runpython.py
<Swig Object of type 'uint16_t *' at 0x7f8261e15b40>swig/python detected a memory leak of type 'uint16_t *', no destructor found.

下面是SWIG3.0文档,特别是"5.5结构和联合“一节:nn31

我做错了什么?

我把这个例子归结为赤裸裸的骨头:

swig_test.h

代码语言:javascript
复制
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

代码语言:javascript
复制
#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

代码语言:javascript
复制
%module swig_test

%{
#include "swig_test.h"
%}

%include "swig_test.h"

Makefile

代码语言:javascript
复制
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

代码语言:javascript
复制
#!/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)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-03-16 23:10:05

您要寻找的功能是在类型映射中实现的。这些文档坦率地承认,“乍一看,这段代码看起来有点混乱。”这就是对我有用的东西。

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

$input是指需要转换为C/C++的输入对象。 $result指的是将由包装器函数返回的对象。 $1指的是一个C/C++变量,其类型与类型地图声明中指定的类型相同(本例中为int )。

对于无符号整数支持,只需为uint8_tuint16_tuint32_t提供进出映射即可。

下面的行提供了该功能。它们可以进入SWIG的.i文件或主标题(在它们周围有一个ifdef SWIG保护)。

代码语言:javascript
复制
/* 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);
}

我认为有用的资源:

票数 3
EN

Stack Overflow用户

发布于 2016-02-24 19:19:16

一个“修正”是将uint16_t成员更改为int类型。然后这个语法起作用了:

代码语言:javascript
复制
print var.mem0

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

如果有人提出另一种解决方案,让我保留我的uint16_t类型,我会很高兴的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35585457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档