栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

类型映射中的SWIG有效,但argout不起作用

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

类型映射中的SWIG有效,但argout不起作用

怎么了?

简而言之,这些类型图不是一个或非命题。

您缺少的关键信息是多个类型映射协作包装单个函数的方式。

argout
在调用发生 后被 插入到生成的包装器中。您有机会以明智的方式将(现在已修改的)输入复制回Python。

但是,这并没有解决在调用之前如何创建和传递参数的问题。

通过检查此接口生成的代码,您可以很清楚地看到这一点:

%module test%{#include "test.h"%}%typemap(in) int[2] {  // "In" typemap goes here}%typemap(argout) int[2] {  // "argout" goes here}%include "test.h"

当您的示例是test.h时,会产生以下结果:

  // ... <snip>  arg1 = reinterpret_cast< Foobar * >(argp1);  {    // "In" typemap goes here  }  (arg1)->method(arg2);  resultobj = SWIG_Py_Void();  {    // "argout" goes here  }  return resultobj;  // ... <snip>

在那些类型映射中,“ in”类型映射的目标是

arg2
在调用之前创建一个有意义的值,而“
argout”类型映射应在调用之后对这些值做一些有意义的操作(如果需要,可以更改返回值)。


类型图中应该是什么?

通常,对于类似这样的函数,您可能希望输入类型图由一些Python输入填充一个临时数组。

为此,我们需要首先更改输入类型图,要求SWIG为我们创建一个临时数组:

重要的是,让SWIG为我们做到这一点,使用在类型之后添加括号的表示法,而不是在类型映射的主体内添加括号,以使作用域对变量正确。(如果我们不这样做,则暂时无法从“
argout”类型映射中访问该临时类型,并且在调用自身之前将其清除)。

%typemap(in) int[2] (int temp[2]) {  // If we defined the temporary here then it would be out of scope too early.  // "In" typemap goes here}

SWIG生成的代码现在为我们包括了该临时数组,因此我们想使用Python C API迭代输入。可能看起来像:

%typemap(in) int[2] (int temp[2]) {  // "In" typemap goes here:  for (Py_ssize_t i = 0; i < PyList_Size($input); ++i) {    assert(i < sizeof temp/sizeof *temp); // Do something smarter    temp[i] = PyInt_AsLong(PyList_GetItem($input, i)); // Handle errors  }  $1 = temp; // Use the temporary as our input}

(如果愿意,我们可以选择使用Python迭代器协议)。

如果现在编译并运行接口,则我们有足够的能力来传递输入,但是什么也没回来。在我们编写“
argout”类型映射之前,在生成的代码中还需要注意一件事。生成的代码中的临时数组实际上看起来像

inttemp2[2]
。没错,SWIG默认情况下已重命名要从参数位置派生的变量,以便允许将同一类型映射多次应用于单个函数调用,如果需要,每个参数一次。

在“ argout”类型图中,我将返回另一个带有新值的Python列表。从长远来看,这并不是唯一明智的选择-如果您愿意,还有其他选择。

%typemap(argout) int[2] {  // "argout" goes here:  PyObject *list = PyList_New(2);  for (size_t i = 0; i < 2; ++i) {    PyList_SetItem(list, i, PyInt_FromLong(temp$argnum[i]));  }  $result = list;}

需要注意的两点是,首先,我们需要

temp$argnum
显式地编写代码以匹配SWIG对临时数组所做的转换,其次,我们将其
$result
用作输出。

纯输出参数

通常,我们有一个仅用于输出而不是输入的参数。对于这些,强制Python用户提供将被忽略的列表是没有意义的。

我们可以通过修改“
in”类型映射来做到这一点,使用

numinputs=0
表示不需要Python输入。您还需要在这里适当地初始化临时文件。现在,类型映射变得简单:

%typemap(in,numinputs=0) int[2] (int temp[2]) {  // "In" typemap goes here:  memset(temp, 0, sizeof temp);  $1 = temp;}

因此,现在“ in”类型映射实际上根本不接受来自Python的任何输入。可以将其视为简单地准备本机调用的输入。

顺便说一句,您可以避免在SWIG中应用名称混乱(因为无法在同一函数上多次使用同一类型图,或者使用另一个具有名称冲突的类型图)

noblock=1

”类型图。我不建议这样做。

非固定数组长度?

最后值得一提的是,我们可以将所有这些类型图编写成更通用的形式,并适用于任何固定大小的数组。为此,我们在类型映射匹配中将2更改为“
ANY”,然后在类型映射

$1_dim0
主体中使用2而不是2,这样,整个接口的末尾变为:

%module test%{#include "test.h"%}%typemap(in,numinputs=0) int[ANY] (int temp[$1_dim0]) {  // "In" typemap goes here:  memset(temp, 0, sizeof temp);  $1 = temp;}%typemap(argout) int[ANY] {  // "argout" goes here:  PyObject *list = PyList_New($1_dim0);  for (size_t i = 0; i < $1_dim0; ++i) {    PyList_SetItem(list, i, PyInt_FromLong(temp$argnum[i]));  }  $result = list;}%include "test.h"


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/414541.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号