簡體   English   中英

指向SWIG中C結構的python指針—訪問struct成員

[英]python pointer to C structure in SWIG — accessing the struct members

我正在嘗試使用SWIG獲得一個非常基本的Python到C的接口,在該接口中我可以將指向結構的指針傳遞給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"

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示例:

運行python.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)

您要尋找的功能來自類型映射。 該文檔自由地承認“乍看之下,這段代碼看起來有些混亂”。 這對我有用。

本質上,類型映射是SWIG需要在Python和C之間轉換時交換的幾行代碼。它們分別是將Python定義為C( %typemap(in) )和將C定義為Python( %typemap(out) )。 SWIG的文檔還定義了一些魔術變量:

$input表示需要轉換為C / C ++的輸入對象。

$result指向將由包裝器函數返回的對象。

$1指的是C / C ++變量,其類型與類型映射聲明中指定的類型相同(在此示例中為int)。

對於無符號整數支持,您只需要uint8_tuint16_tuint32_t輸入和輸出映射

下面的行提供了該功能。 它們可以進入SWIG的.i文件或主標頭(帶有ifdef SWIG防護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類型,我將非常喜歡。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM