在 SWIG argout 类型映射中使用结构 [英] Use struct in SWIG argout typemap

查看:43
本文介绍了在 SWIG argout 类型映射中使用结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从 Python 调用一个 C 函数,它应该创建并初始化一个结构体.我希望这个结构体转换为 Python 对象作为 Python 中的返回值.

I want to call a C function from Python, which should create and initialize a struct. I want this struct converted to a Python object as the return value in Python.

推荐答案

这里是示例文件(基于 访问 C 结构体数组到 Python与 SWIG) 实现我想要的,即 create_struct() 创建并初始化一个结构,它可以在 Python 中使用.感谢 John Bollinger 帮助修复错误.

Here are example files (based on Accessing C struct array to Python with SWIG) which achieve what I want, i.e. create_struct() creates and initializes a struct, which can be used in Python. Thanks to John Bollinger for helping to fix bugs.

#include <stdint.h>

struct Foo
{
  uint8_t a[4];
};

void create_struct(struct Foo** new_struct);

example.c

#include <string.h>
#include "example.h"

void create_struct(struct Foo** new_struct){
    struct Foo* foo = (struct Foo*) malloc(sizeof(struct Foo));
    uint8_t tmp[4] = {0,1,2,3};
    memcpy(foo->a, tmp, 4);
    *new_struct = foo;
}

example.i

%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}

// Define input and output typemaps for a

%typemap(in) uint8_t a[4] {
  if (!PyBytes_Check($input)) {
    PyErr_SetString(PyExc_TypeError, "Expecting a bytes parameter");
    SWIG_fail;
  }

  if (PyObject_Length($input) != 4) {
    PyErr_SetString(PyExc_ValueError, "Expecting a bytes parameter with 4 elements");
    SWIG_fail;
  }

  uint8_t res[4];
  char* bytes = PyBytes_AsString($input);
  int i;
  for (i=0; i<4; i++) {
    res[i] = (uint8_t) bytes[i];
  }

  $1 = res;
}

%typemap(out) uint8_t a[4] {
    $result = PyBytes_FromStringAndSize((char*) $1, 4);
}

/*
 * This fails with "Warning 453: Can't apply (struct Foo *OUTPUT). No typemaps are defined.":
 *   %apply struct Foo* OUTPUT {struct  Foo* new_struct };
 * So I'm trying to define typemaps for struct Foo*
 */

// This typemap suppresses requiring the parameter as an input.
%typemap(in,numinputs=0) struct Foo** new_struct (struct Foo* temp) {
  $1 = &temp;
}

%typemap(argout) struct Foo** new_struct {
    $result = SWIG_NewPointerObj(*$1, $descriptor(struct Foo*), SWIG_POINTER_OWN);
}

%include "example.h"

extern void create_struct(struct Foo** new_struct);

setup.py

#!/usr/bin/env python3

from distutils.core import setup, Extension

module1 = Extension('example', sources=['example.c', 'example.i'])
setup(name='Example', version='0.1', ext_modules=[module1])

test.py

#!/usr/bin/env python3

import example
foo = example.create_struct()
print("foo.a: %r" % foo.a)

构建和执行:

python3 setup.py build_ext --inplace && mv example.*.so _example.so && python3 test.py

测试代码应该打印foo.a: b'\x00\x01\x02\x03'.

这篇关于在 SWIG argout 类型映射中使用结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆