SWIG:如何使用%apply返回结构? 'No typemaps defined'警告

SWIG: How to return a struct using %apply? 'No typemaps defined' warning

本文关键字:No typemaps 警告 defined 何使用 %apply 结构 返回 SWIG      更新时间:2023-10-16

我目前有一个函数,它使用结构体作为缓冲区来返回一些信息,如下所示:

int example_reader(int code, void* return_struct);

我的目标是这样做,当我使用SWIG包装这个函数以便它可以在Python中使用时,我将返回结构体以及函数的常规返回值。到目前为止,我一直使用%apply命令,如下所示:

%apply struct ret_struct *OUTPUT {void* return_struct};

但是,当我将上面的行添加到我的。I文件并尝试运行SWIG时,我得到以下警告:

" Can't apply (struct ret_struct *OUTPUT。没有定义类型映射"

我相信我正在包括定义我试图返回的结构体的.h文件,所以我很难确定问题。如果问题似乎涉及结构的不当包含,请纠正我。我试着通读SWIG文档以及其他Stack Overflow帖子,以获得问题可能是什么的一些线索,但到目前为止我还没有能够弄清楚。这个问题变得有点棘手,因为我试图返回一个指向结构体的void指针,而我试图包装的代码可能有多种类型的结构体供我返回。处理这个结构返回的明智方法是什么?谢谢你!

我在这里给出了一个完整的C示例,其中使用接口将结构体与返回值一起返回到目标语言。通过这种方式,您可以在头文件中没有给出实现的情况下创建合适的接口。这不是虚析构函数的默认实现。如果不想使用接口,可以让SWIG和Python知道数据是如何表示的。

接口头:foo.h

typedef struct _Foo Foo;
int foo_new(Foo **obj);
int foo_free(Foo *obj);
int foo_get_value_a(Foo *obj, int *result);
int foo_set_value_a(Foo *obj, int value);
int foo_get_value_b(Foo *obj, char **result);
int foo_set_value_b(Foo *obj, char *value);

SWIG接口:foo.i

%module foo
%{
#include "foo.h"
%}
%include "typemaps.i"
%typemap(in, numinputs=0) Foo ** (Foo *temp) {
  $1 = &temp;
}
%typemap(argout) Foo ** {
  PyObject* temp = NULL;
  if (!PyList_Check($result)) {
    temp = $result;
    $result = PyList_New(1);
    PyList_SetItem($result, 0, temp);
  }
  temp = SWIG_NewPointerObj(*$1, SWIGTYPE_p__Foo, SWIG_POINTER_NEW);
  PyList_Append($result, temp);
  Py_DECREF(temp);
}
%delobject foo_free; // Protect for double deletion
struct _Foo {};
%extend _Foo {
  ~_Foo() {
    foo_free($self);
  }
};
%ignore _Foo;

接口的一些实现:foo.c

%include "foo.h"
#include "foo.h"
#include "stdlib.h"
#include "string.h"
struct FooImpl {
  char* c;
  int i;
};
int foo_new(Foo **obj)
{
  struct FooImpl* f = (struct FooImpl*) malloc(sizeof(struct FooImpl));
  f->c = NULL;
  *obj = (Foo*) f;
  return 0;
}
int foo_free(Foo *obj)
{
  struct FooImpl* impl = (struct FooImpl*) obj;
  if (impl) {
    if (impl->c) {
      free(impl->c);
      impl->c = NULL;
    }
  }
  return 0;
}
int foo_get_value_a(Foo *obj, int *result)
{
  struct FooImpl* impl = (struct FooImpl*) obj;
  *result = impl->i;
  return 0;
}
int foo_set_value_a(Foo *obj, int value)
{
  struct FooImpl* impl = (struct FooImpl*) obj;
  impl->i = value;
  return 0;
}
int foo_get_value_b(Foo *obj, char **result)
{
  struct FooImpl* impl = (struct FooImpl*) obj;
  *result = impl->c;
  return 0;
}
int foo_set_value_b(Foo *obj, char *value)
{
  struct FooImpl* impl = (struct FooImpl*) obj;
  int len = strlen(value);
  if (impl->c) {
    free(impl->c);
  }
  impl->c = (char*)malloc(len+1);
  strcpy(impl->c,value);
  return 0;
}

创建脚本

#!/usr/bin/env python
from distutils.core import setup, Extension
import os
os.environ['CC'] = 'gcc';
setup(name='foo',
      version='1.0',
      ext_modules =[Extension('_foo',
                              ['foo.i','foo.c'])])

用法:

import foo
OK, f = foo.foo_new()
OK = foo.foo_set_value_b(f, 'Hello world!')
OK = foo.foo_free(f)
OK, f = foo.foo_new()
# Test safe to double delete
del f