Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何为双指针结构参数应用SWIG类型映射_Python_C_Pointers_Swig - Fatal编程技术网

Python 如何为双指针结构参数应用SWIG类型映射

Python 如何为双指针结构参数应用SWIG类型映射,python,c,pointers,swig,Python,C,Pointers,Swig,我有一个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 *li

我有一个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\u t

所有其他的都只有一个指针,例如

void print_hash_tracks(const track_t *hash_tracks, const cfg_t *cfg,
                       enum TRKTYPE trktype);
我很确定我需要在我的SWIG接口文件(interface.I)中创建一个类型映射,但是我发现SWIG文档无法穿透

我想我需要做的是创建一个类型映射,每当它看到
track\u t**
类型时,它就会获取一个
track\u 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方面

我觉得我几乎解决了这个问题,但不能完全正确地获得typemap规范,同时努力理解相关文档

柔印-如果你在那里-也许你能对此有所了解,你似乎是这方面的专家

更新-m7ython(太棒了!另一位SWIG专家在SO上)

C语言中的用法非常简单

声明并初始化指向NULL的跟踪指针:

track_t *hash_tracks = NULL;
然后:

因此指向
track\u t
的指针的地址作为参数传递给
update\u tracks()
update\u tracks()
fn为放入
hash\u tracks
的数据处理所有必要的malloc,即
track\u t
结构的哈希表

所有其他参数都是单指针,我可以创建和填充它们,而python方面没有任何问题

track\u 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库)<代码>哈希轨道指向哈希表中的第一个轨道。在
update_tracks()
fn track_t结构体中,可以从哈希表中添加/删除结构,以便指向第一个轨迹的指针可能会更改,即
hash_tracks()调用
update_tracks()
后可能指向其他对象,因此需要将指针传递给指针

换句话说,
track\u t**
arg、
phash\u tracks
被用作输入和输出类型arg,因此是指向指针的指针。所有其他参数都只是输入,它们不会更改,因此可以作为单指针传入

我使用以下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_轨道为空

这是编译和包装的,没有错误,但当我从python端使用它时,它会出错,例如

phash_tracks = g3.make_phash_tracks()
g3.update_tracks(phash_tracks, pdw_frame, rdw_frame, lib, lib_meta, cfg)
在调用
update\u tracks
之前检查
phash\u tracks
var,给出:

(Pdb) p phash_tracks
<Swig Object of type 'track_t **' at 0x7fb9e37c9030>
(Pdb)p相轨道

编辑:好的,我想我现在明白了
更新曲目的作用了。您似乎可以通过两种方式使用该函数。如果将指针传递给
NULL
指针,则可以更新现有
磁道
,也可以创建
磁道
。我不确定在SWIG中处理这两种情况的最优雅的方法是什么(或者这是否是一个问题),但这里有一些选择

1. <代码>相位跟踪
是一个输出参数 首先,您必须将
*phash_tracks
作为返回值传递回Python,并以如下形式使用函数

>>> int_res, tracks = g3.update_tracks(tracks, pdw_frame, rdw_frame, lib, lib_meta, cfg)

这是通过以下“argout”类型映射实现的:

也许您不希望Python拥有
跟踪*
,然后用
0
替换
SWIG\u指针

2.通过空的
phash_轨道
如果您只想使用
update_tracks
功能来创建
曲目
,则基本上可以执行您已经在执行的操作。使用下面的“in”类型映射,并使用上面第二个示例中的函数(不带
tracks
参数)

3. <代码>相位跟踪
作为输入(和输出)参数 如果您想使用
update\u tracks
来更新现有的
tracks
,您应该能够使用我之前建议的“in”类型映射,并像第一个示例一样使用Python中的函数(包括
tracks
参数)

请注意,Python不承认它的
跟踪
,这一点很重要

%typemap(in) track_t **phash_tracks (track_t *tracks) {
  // Alternatively, check if $input is a 0 integer `PyObject`...
  if ((SWIG_ConvertPtr($input, (void **) &tracks, $*1_descriptor, SWIG_POINTER_DISOWN)) == -1)
    tracks = NULL;
  $1 = &tracks;
}
4.同时启用上述(2)和(3) 如果您可以让swig通过一个包装的
NULL
轨道*
,那么基本上也可以使用版本(3)来创建
轨道。我不确定SWIG是否允许这样做,但也许它允许。尝试使用辅助函数:

tracks_t* empty_tracks() { return NULL; }
或者,您可以沿以下行修改“in”类型映射,尝试将提供的参数转换为
track\t*
并传递其地址,或者传递
NULL
track\t*
的地址

%typemap(in) track_t **phash_tracks (track_t *tracks) {
  // Alternatively, check if $input is a 0 integer `PyObject`...
  if ((SWIG_ConvertPtr($input, (void **) &tracks, $*1_descriptor, SWIG_POINTER_DISOWN)) == -1)
    tracks = NULL;
  $1 = &tracks;
}
然后,从Python中,只需传递其他内容来创建
曲目

>>> int_res, tracks = g3.update_tracks(0, pdw_frame, rdw_frame, lib, lib_meta, cfg)

我不知道SWIG,但是看看函数调用,你确定你正确地传递了双指针吗?似乎您传递的不是
磁道的地址,而是值本身。TBH如果您不知道SWIG,则可能无法提供太多信息。typemap正在尝试将轨迹指针转换为双指针。它被合并到自动生成的包装器代码中,我相信您可以用C语言给出一个示例,说明如何使用
update\u tracks
?当前,您的类型映射将
轨迹**
传递给未初始化的
轨迹*
,并且在函数完成后不使用
轨迹**
。如果你能得到你的手
%typemap(in) track_t **phash_tracks (track_t *tracks) {
  if ((SWIG_ConvertPtr($input, (void **) &tracks, $*1_descriptor, SWIG_POINTER_EXCEPTION | SWIG_POINTER_DISOWN)) == -1)
    return NULL;
  $1 = &tracks;
}
tracks_t* empty_tracks() { return NULL; }
%typemap(in) track_t **phash_tracks (track_t *tracks) {
  // Alternatively, check if $input is a 0 integer `PyObject`...
  if ((SWIG_ConvertPtr($input, (void **) &tracks, $*1_descriptor, SWIG_POINTER_DISOWN)) == -1)
    tracks = NULL;
  $1 = &tracks;
}
>>> int_res, tracks = g3.update_tracks(0, pdw_frame, rdw_frame, lib, lib_meta, cfg)