【问题标题】:OUT argument internally allocated to return an array of structsOUT 参数在内部分配以返回结构数组
【发布时间】:2013-06-19 21:58:11
【问题描述】:

我是 swig 的新手,我有以下无法修复的功能:

int get_list(IN const char * string, OUT struct entry ** results);

struct entry 的定义位置:

struct flux_entry
{
    char * addr_str;
    char cc[2];
};

入口结构已正确转换为 python 类。 我用谷歌搜索但找不到任何我可以使用的解释。
我想让它返回一个元组:(原始get_list int 返回值,python 条目 python 对象列表,基于结果缓冲区),但不知道如何将 C 条目转换为 python argout 代码 sn-p 中的对象。 到目前为止,我已经成功了:

%typemap(argout) struct entry **
{
    PyObject *o = PyList_New(0);
    int i;
    for(i=0; $1[i] ; i++)
    {
        PyList_Append(o, SWIG_HOW_TO_CONVERT_TO_PYOBJECT($1[i]));
    }
    $result = o;
}

我应该用什么替换SWIG_HOW_TO_CONVERT_TO_PYOBJECT? 传递的results 应该是指向 (struct entry *) 类型的指针,在调用get_list 之前设置为NULL,并且应该设置为struct entry * 指针的分配数组。也许一个小的包装函数可以让这更容易?

struct entry 数组是在 C 函数中使用 malloc 分配的,在计算(在 get_list 内)需要多少元素之后,并以 NULL 指针结尾以指示数组的结尾。

我还想确保它在某处被释放:)

谢谢!

【问题讨论】:

  • 你怎么知道有多少struct entry 对象输出? struct entry的定义是什么?
  • @MarkTolonen:编辑问题以提供额外的细节
  • 我实际上想做一些与这个人想要的非常相似的事情:stackoverflow.com/questions/5822529/… 但我有一个结构条目指针数组而不是双精度...

标签: python swig


【解决方案1】:

这至少应该为您提供一个可行的起点。我仍然不确定数据是如何返回的,因为要返回一个指针数组以便最后一个为 NULL 我认为你需要一个struct entry ***,所以我只是在最后一个上设置了addr_str = NULL作为哨兵,只需将部分基于输入字符串的虚拟数据放入字段中。根据需要进行修改以满足您的需要:

%module example

// Insert the structure definition and function to wrap into the wrapper code.
%{
  struct entry {
    char* addr_str;
    char cc[2];
  };

  int get_list(const char* string, struct entry** results)
  {
    *results = malloc(3 * sizeof(struct entry));
    (*results)[0].addr_str = malloc(10);
    strcpy((*results)[0].addr_str,"hello");
    (*results)[0].cc[0] = string[0];
    (*results)[0].cc[1] = string[1];
    (*results)[1].addr_str = malloc(10);
    strcpy((*results)[1].addr_str,"there");
    (*results)[1].cc[0] = string[2];
    (*results)[1].cc[1] = string[3];
    (*results)[2].addr_str = NULL;
    return 0;
  }
%}

#include <typemaps.i>

// Define the structure for SWIG
struct entry {
  char* addr_str;
  char cc[2];
};

// Define a set of typemaps to be used for an output parameter.

// This typemap suppresses requiring the parameter as an input.
// A temp variable is created and passed instead.
%typemap(in,numinputs=0) struct entry **OUTPUT (struct entry* temp) %{
  $1 = &temp;
%}

// Build a list of tuples containing the two entries from the struct.
// Append the new Python list object to the existing "int" result.
%typemap(argout) struct entry **OUTPUT {
  int i = 0;
  PyObject* out = PyList_New(0);
  while((*$1)[i].addr_str != NULL)
  {
    //PyObject* t = PyTuple_New(2);
    //PyTuple_SET_ITEM(t,0,PyBytes_FromString((*$1)[i].addr_str));
    //PyTuple_SET_ITEM(t,1,PyBytes_FromStringAndSize((*$1)[i].cc,2));
    //PyList_Append(out,t);
    //Py_DECREF(t);
    PyObject* s = SWIG_NewPointerObj(*$1+i,$descriptor(struct entry*),0);
    PyList_Append(out,s);
    Py_DECREF(s);
    ++i;
  }
  $result = SWIG_AppendOutput($result,out);
}

// Since a Python object was created and the data copied for each entry struct,
// free the memory returned in the structure.
//%typemap(freearg) struct entry **OUTPUT {
//  int i=0;
//  while((*$1)[i].addr_str != NULL) {
//    free((*$1)[i].addr_str);
//    ++i;
//  }
//  free(*$1);
//}

// Apply the OUTPUT typemap set to the "results" parameter.
%apply struct entry **OUTPUT {struct entry** results};

// Finally, define the function for SWIG
int get_list(const char* string, struct entry** results);

演示(Python 3.3):

>>> import example
>>> example.get_list('abcd')
[0, [(b'hello', b'ab'), (b'there', b'cd')]]

希望对您有所帮助。

编辑

我注释掉了元组的创建,只保存了entry* 代理。这不会泄漏 Python 对象,但分配给 entry* 使用的内存不会被释放。虽然我正在尝试使用%extend,但我不确定该放在哪里。

【讨论】:

  • 实际上,这段代码将返回一个元组,而不是我的条目 struc 的对象,对吧?另一个问题 - 你为什么PyDECREF-ed t?
  • 是的,我将数据反映为一个元组,但如果您想将其保留为 SWIG 代理对象,也可以这样做。 decref 是因为 Python 对象是引用计数的,我已经完成了元组。没有它会发生内存泄漏。
  • 我怎样才能拥有一个 swig 代理?如果我的答案不清楚,这就是我的最终目标。元组不是还在被它附加到的列表中使用吗?谢谢!
  • 添加到列表时,元组的引用计数会增加。当我完成它时,我减少了计数,使其计数为 1。当列表被释放时,它会减少它的每个元素。如果您构建 Python 的调试版本,您可以看到所有 Python 对象的引用计数总和,因此一遍又一遍地运行该命令会发现任何泄漏。
  • @Nirlzr,请参阅我上面的编辑以返回代理对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
  • 2014-04-21
相关资源
最近更新 更多