通过 swig 为 python-C++ 接口禁用隐式类型检查代码的生成

Posted

技术标签:

【中文标题】通过 swig 为 python-C++ 接口禁用隐式类型检查代码的生成【英文标题】:Disable generation of implicit type checking code by swig for python-C++ interface 【发布时间】:2017-10-02 10:33:13 【问题描述】:

对于以下简单函数:

#include <iostream>
void Echo(int no) 
    std::cout << "no: " << no << std::endl;

我有以下swig接口文件:

%module example
%
#include "example.h"
%
%include "example.h"

我可以使用 swig 生成一个包装器并将其测试为:

from example import Echo
import numpy as np

no = 2
Echo( np.int(no) )      # OK
Echo( np.int32(no) )    # Error
Echo( np.int64(no) )    # Error

swig 生成类型检查包装器代码,导致第二次和第三次调用出错。这很好,但是有什么方法可以覆盖/禁用为合法的类型转换生成这种类型检查代码?

【问题讨论】:

您可以使用%renameEcho 重命名为EchoInternal,并使用%insert("python") 添加一个函数Echo,该函数将转换为int 并调用EchoInternal。没有旗帜可以引入某种放松 【参考方案1】:

这可以通过在生成包装器时将 castmodenocastmode 选项传递给 swig 来控制。默认值为nocastmode。这不需要定义任何typemaps,也独立于python2/python3。

示例:要允许上面示例中的类型转换,可以将包装器生成为:

swig -c++ -python -castmode example.i

【讨论】:

【参考方案2】:

您可以使用 SWIG 编写具有所需语义的类型映射。默认 int 类型映射对您不起作用的原因是它显式调用 PyLong_Check,这要求您的输入是 int 或其子类型。 numpy 类型不是这种情况,因此它会被拒绝,但是如果我们跳过该检查并直接跳转到PyLong_AsLong,那么它将最终隐式调用__int__ 方法以使转换成为可能。

所以把你的 SWIG 模块改成这样:

%module example
%
#include "example.h"
%
%typemap(in) int %
  // Skips PyLong_Check and calls PyLong_AsLong, which calls __int__ as needed
  $1 = PyLong_AsLong($input);
  // But be aware of overflow semantics here. And note py3/py2 differences in PyLong/PyInt
  //
%
%include "example.h"

足以让您的示例通过。

请注意,您也可以通过使用 SWIG 的重载解析机制在 SWIG 中实现相同的目标。

【讨论】:

以上是关于通过 swig 为 python-C++ 接口禁用隐式类型检查代码的生成的主要内容,如果未能解决你的问题,请参考以下文章

在使用许多 SWIG 生成的模块时避免重复的 SWIG 样板

如何在 swig & python 中为没有默认构造函数的 std::pair<> 创建接口?

SWIG包装器未声明(此功能首次使用)

Android - proguard 忽略 -keep 的 Swig 方法

Swig:返回向量的接口简单 C++ 类

Swig 中 C 指针的访问器函数