我有一个API,我试图使用SWIG包装,以便我可以从python调用底层的C库 .
我遇到了一个特定的API fn:
int update_tracks(track_t **phash_tracks,
const pdws_t *pdw_frame,
const rdws_t *rdw_frame,
lib_t *lib,
lib_meta_t *lib_meta,
const cfg_t *cfg);
它是 track_t
数据结构的双指针,我无法处理 .
所有单指针都可以正常工作 .
这是唯一一个具有指向 track_t
的双指针的API fn
所有其他只有一个指针,例如
void print_hash_tracks(const track_t *hash_tracks, const cfg_t *cfg,
enum TRKTYPE trktype);
我很确定我需要在SWIG界面文件(interface.i)中创建一个类型图,但我发现SWIG文档难以理解 .
我认为我需要做的是创建一个类型图,每当它看到 track_t**
类型时,需要 track_t*
并将其转换为其地址,如:
/* provide typemap to handle instances of track_t** parameters */
%typemap(in) track_t** (track_t *tracks) {
$1 = &tracks;
}
但是当我跑步时,我只是出现了分段错误:
tracks = g3.track_t()
g3.update_tracks(tracks, pdw_frame, rdw_frame, lib, lib_meta, cfg)
在python方面 .
我觉得我几乎已经解决了这个问题,但是无法正确地获得类型图规范,同时也在努力理解相关文档 .
柔印 - 如果你在那里 - 也许你可以对此有所了解,你似乎是这方面的SO专家..
更新 - m7ython(太棒了!SO的另一位SWIG专家)
C中的用法非常简单
声明并初始化一个指向NULL的track_t指针:
track_t *hash_tracks = NULL;
然后:
update_tracks(&hash_tracks, &pdw_frame, &rdw_frame,
&lib, &lib_meta, &cfg);
因此,指向 track_t
的指针的地址作为arg传递给 update_tracks()
. update_tracks()
fn负责处理放入 hash_tracks
的数据的所有必要malloc,即 track_t
结构的哈希表
所有其他args都是单指针,我可以创建并填充它们,而python方面没有任何问题 .
track_t
是一个包含一堆整数,浮点数,字符*等的结构,例如
typedef struct
{
/* make struct hashable */
UT_hash_handle hh;
int id;
...
char name[MAX_BUF];
...
} track_t;
track_t arg是 track_t**
而不仅仅是 track_t*
的原因是因为 hash_tracks
是指向哈希表的指针(使用UTHash库) . hash_tracks
指向哈希表中的第一个track_t . 在 update_tracks()
fn track_t的主体中,可以在哈希表中添加/删除结构,这样第一个track_t的指针可能会改变,即 hash_tracks
可能在调用 update_tracks()
之后指向其他东西,因此传递指针的原因指针 .
换句话说, track_t**
arg, phash_tracks
既被用作输入和输出类型arg,因此指向指针 . 所有其他args只是输入,它们不会改变,所以它们可以作为单个指针传入 .
我用以下C fn尝试了'helper fn'路由:
track_t** make_phash_tracks(void)
{
track_t **phash_tracks;
phash_tracks = calloc(1, sizeof(track_t*));
return phash_tracks;
}
使用calloc应该确保* phash_tracks为NULL
这个编译和包装没有错误,但是当我从python一侧使用它时,它会被分段,例如
phash_tracks = g3.make_phash_tracks()
g3.update_tracks(phash_tracks, pdw_frame, rdw_frame, lib, lib_meta, cfg)
在调用 update_tracks
之前检查 phash_tracks
var给出:
(Pdb) p phash_tracks
<Swig Object of type 'track_t **' at 0x7fb9e37c9030>
1 回答
编辑:好的,我想我现在明白
update_tracks
的作用了 . 看来你可以用两种方式使用这个功能 . 如果您将指针传递给NULL
指针,则更新现有的tracks
或创建tracks
. 我不确定在SWIG中处理这两种情况的最优雅的方法(或者如果这甚至是一个问题),但这里有一些选择 .1. phash_tracks是输出参数
首先,您 must 将
*phash_tracks
传递回Python作为返回值,并以某种形式使用该函数要么
这是通过以下“argout”类型映射完成的:
也许您不希望Python获得
track_t*
的所有权,然后将SWIG_POINTER_OWN
替换为0
.2.传递空的phash_tracks
如果您只想使用
update_tracks
函数创建tracks
,您可以基本上完成您已经在做的事情 . 使用以下"in" typemap,并使用上面第二个示例中的函数(不带tracks
参数) .3. phash_tracks作为输入(和输出)参数
如果要使用
update_tracks
来更新现有的tracks
,您应该能够使用我之前建议的"in"类型映射,并使用Python中的函数,如第一个示例(包括tracks
参数) .请注意,Python必须将其
tracks_t*
拒绝 .4.启用上面的(2)和(3)
您基本上可以使用版本(3)创建
tracks
,如果您可以通过swig传递包装的NULL
tracks_t*
. 我不确定SWIG是否允许这样做 - 但也许确实如此 . 尝试使用辅助函数:或者,你可以沿着以下行修改"in"类型映射,尝试将提供的参数转换为
track_t*
并传递其地址,或者传递NULL
track_t*
的地址 .然后,从Python中,只需传递其他内容即可创建
tracks
: