我是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条目到argout代码片段中的python对象。
到目前为止,我已经成功了:
%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 *)类型的指针,在调用NULL
之前设置为get_list
,并且应该设置为已分配的struct entry *
指针数组。也许一个小的包装函数可以使这更容易?
struct entry
之内)需要多少个元素后,malloc
数组在C函数内使用get_list
分配,并以NULL
指针结束表示数组的结束。
我也想确保它在某个地方被释放:)
谢谢!
答案 0 :(得分: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*
使用的malloced内存。虽然我正在试验%extend
,但我不知道该把它放在哪里。