次の SWIG インターフェイス ファイルがあるとします。
%include "std_string.i"
%module Test %{
std::string AmIABoolean(bool b)
{
return b ? "Sure" : "Yes I am";
}
%}
std::string AmIABoolean(bool b);
Python からこのモジュールに接続する場合、これは実際にブール値を渡すときにうまく機能します。
>>> Test.AmIABoolean(False)
"Yes I am"
>>> Test.AmIABoolean(True)
'Sure'
しかし、驚いたことに (そしてがっかりしたこと)、SWIG はこの特定のテスト関数に対して任意の引数を受け入れます。
>>> Test.AmIABoolean([])
"Yes I am"
>>> Test.AmIABoolean("Free beer")
'Sure'
SWIG が C++ を python メソッドに一致させる方法で、より厳密な型チェックを強制する方法はありますか? 明らかに、この例はあまり意味がありませんが、複数のオーバーロードを持つメソッドがあり、そのうちの 1 つがブール値の引数を受け入れる場合、これは SWIG がブール値を受け入れる特定のオーバーロードを常に使用することを意味し、これは非常に望ましくありません。
インターフェイス ファイルで SWIG がブール型をチェックする方法を見ると、この動作はそれほど驚くべきことではありません。
SWIGINTERN int
SWIG_AsVal_bool (PyObject *obj, bool *val)
{
int r = PyObject_IsTrue(obj);
if (r == -1)
return SWIG_ERROR;
if (val) *val = r ? true : false;
return SWIG_OK;
}
Pythonのドキュメントには、PyObject_IsTrueについて次のように書かれています
オブジェクト o が true であると見なされる場合は 1 を返し、そうでない場合は 0 を返します。これは、Python の式 not not o と同等です。失敗すると -1 を返します。
動的型付けの素晴らしい世界では、「無料のビール」は常に true と評価されます
>>> not not "Free beer"
True
しかし、確かに SWIGは真の値とたまたま真と評価される値を区別できなければなりません。どんな助けでも大歓迎です。