通过 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 生成类型检查包装器代码,导致第二次和第三次调用出错。这很好,但是有什么方法可以覆盖/禁用为合法的类型转换生成这种类型检查代码?
【问题讨论】:
您可以使用%rename
将Echo
重命名为EchoInternal
,并使用%insert("python")
添加一个函数Echo
,该函数将转换为int
并调用EchoInternal
。没有旗帜可以引入某种放松
【参考方案1】:
这可以通过在生成包装器时将 castmode
或 nocastmode
选项传递给 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<> 创建接口?