C++ の shared_ptr に保持されているオブジェクトがあります。オブジェクトは、python 内から python バインディングを介してアクセスされ、それを保持しようとする別のバインドされた C++ 関数に渡されます。オブジェクトが C++ から Python に移行すると、shared_ptr から Python オブジェクトに変換されるようです。その後、C++ に戻ると、python オブジェクトから新しい shared_ptr に変換されますが、この shared_ptr は、最初に保持されていた shared_ptr とは無関係です。
python オブジェクトから shared_ptr への変換が元の shared_ptr 内部を参照するように、boost-python バインディングをセットアップすることは可能ですか?
以下は、問題を示すために使用した要約コードです。
この例では、オブジェクトは最初に s_initial という名前の shared_ptr に保持されます。これは、getSharedPtr 関数を介して Python 内から取得され、putSharedPtr 関数を介して C++ にプッシュされます。putSharedPtr 内では、weak_ptr s_copied にコピーされます。デバッガーでポインターを調べると、putSharedPtr で使用されている shared_ptr が、s_initial と同じ参照カウント内部構造を持っていないことがわかります。ウィーク ポインター s_copied は 1 つのストロング ポインター (putSharedPtr で使用されるポインター) にのみ関連付けられており、putSharedPtr が完了するとそのポインターは破棄されたため、最終的なアサートが発生します。
static shared_ptr<Captured> s_initial;
static weak_ptr<Captured> s_copied;
class UseSharedPtr
{
public:
shared_ptr<Captured> getSharedPtr()
{
return s_initial;
}
void putSharedPtr(shared_ptr<Captured> ptr)
{
s_copied = ptr;
}
};
BOOST_PYTHON_MODULE(test)
{
class_<Captured, shared_ptr<Captured>, boost::noncopyable>("Captured", no_init);
class_<UseSharedPtr, boost::noncopyable>("UseSharedPtr", init<>())
.def("getSharedPtr", &UseSharedPtr::getSharedPtr)
.def("putSharedPtr", &UseSharedPtr::putSharedPtr)
;
}
s_initial = make_shared<Captured>();
const char* chunk = "\
from test import UseSharedPtr \n\
x = UseSharedPtr() \n\
ptr = x.getSharedPtr() \n\
x.putSharedPtr(ptr)\n\
del x \n\
del ptr \n\
";
object result = exec(chunk, mainNamespace, mainNamespace);
assert(s_copied.lock());