std::shared_ptr
タイプとしてラップされているときに、std::map
の標準アクセサー関数を使用できないような、C++クラスへのSWIG生成のPythonラッパーに関する奇妙な問題が発生しています。私は観察している奇妙な行動を再現するMWEを作り出しました。SWIG:shared_ptrでstd :: mapアクセサを使用しますか?
TestMap.hが
#include <iostream>
#include <map>
#include <memory>
class fooType{
public:
fooType() { };
~fooType() { };
void printFoo() { std::cerr << "FOO!" << std::endl; }
static std::shared_ptr<fooType> make_shared() {
return std::shared_ptr<fooType>(new fooType());
}
};
class testMap : public std::map<int, std::shared_ptr<fooType> > {
public:
void printBar() { std::cerr << "bar." << std::endl; }
};
そして、私のSWIGインタフェースファイル:
TestMap.i
%module TestMap
%include <std_map.i>
%include <std_shared_ptr.i>
%{
#include "TestMap.h"
%}
%shared_ptr(fooType);
%shared_ptr(testMap);
%shared_ptr(std::map<int, std::shared_ptr<fooType> >);
%template(fooMap) std::map< int, std::shared_ptr<fooType> >;
%include "TestMap.h"
最後に、私が使用しているテストスクリプトをテストしますインターフェイス外:
AS-書かtest_interface.py
import TestMap as tm
ft = tm.fooType.make_shared()
myTestMap = tm.testMap()
myTestMap[1] = ft
私はマップのアクセサを使用しようとすると、私は次のエラーを取得する:
Traceback (most recent call last):
File "test_interface.py", line 9, in <module>
myTestMap[1] = ft
File "/home/sskutnik/tstSWIG/TestMap.py", line 217, in __setitem__
return _TestMap.fooMap___setitem__(self, *args)
NotImplementedError: Wrong number or type of arguments for overloaded function 'fooMap___setitem__'.
Possible C/C++ prototypes are:
std::map< int,std::shared_ptr<fooType> >::__setitem__(std::map< int,std::shared_ptr<fooType> >::key_type const &)
std::map< int,std::shared_ptr<fooType> >::__setitem__(std::map< int,std::shared_ptr<fooType> >::key_type const &,std::map< int,std::shared_ptr<fooType> >::mapped_type const &
私はft
とmyTestMap
の種類を確認すると、両方のそれぞれのクラスのstd::shared_ptr
参照:
<TestMap.fooType; proxy of <Swig Object of type 'std::shared_ptr<fooType> *' at 0x7fa812e80a80> >
<TestMap.testMap; proxy of <Swig Object of type 'std::shared_ptr<testMap> *' at 0x7fa812e80c90> >
今、奇妙な部分について - SWIGインターフェイスファイルから%shared_ptr(TestMap)
宣言を省略して再コンパイルすると、マップアクセサ(test_interface.py)がうまく動作します。私はmyTestMap
の種類を確認すると、それはです:
<TestMap.testMap; proxy of <Swig Object of type 'testMap *' at 0x7f8eceb50630> >
ので、二つの質問:
- はなぜ私のアクセサは、ときに私はSWIGオブジェクトのポインタ参照(
testMap*
)を持っている場合、正しく作業を呼び出すのではなく、私はshared_ptr
のリファレンスを持っています(例えばstd::shared_ptr<testMap> *
)? - 派生したマップタイプに
shared_ptr
が必要な場合、これを回避するにはどうすればよいですか?
ボーナス質問:私はtestMap
タイプにshared_ptr
タイプが存在することを宣言した場合、なぜSWIGが自動的に(それはのような初期化されていないだ場合でも?)std::shared_ptr<testMap>
型にtestMap*
を変換しない
「ボーナスの質問」: '%shared_ptr(testMap)'は '%template(testMap)shared_ptr'と同じです。そのようなtestMapセマンティクスの変更を避けるには、 '%template(testMapPtr)shared_ptr 'を使用してください。 –
luart
この説明はほとんどの場合私には意味があります。私が気づいたことは、たとえtestMapのためのnull以外のshared_ptrを明示的に作成するメソッドを作成したとしても、私は同じ問題があることです。 しかし、私は、共有ポインタテンプレート(例えば '%template(testMapPtr)std :: shared_ptr')からtestMapの定義を除外したとき、代わりにアイテム割り当て演算子が スマートポインタテンプレートを基底クラスから分離し、スマートポインタ型を持たなければならないときに代替関数を使用しています。ありがとう! –
あなたは歓迎です。 '%template(testMapPtr)shared_ptr'は最初は空の 'testMapPtr'共有ポインタを返しますが、'%shared_ptr(testMap) 'は実際に' testMap'インスタンスで既に初期化されている透過shared_ptrを作成します私はそれを答えに加えます。 –
luart