在使用Boost.Python和C++時,有時我們會創建使用類本身和boost::shared_ptr<>
版本綁定的類。這是非常方便的原因很多,可以在很多地方使用。 但是,當boost::python
將boost::shared_ptr<>
返回爲在Python中生成的值並記錄在C++靜態變量上時,該機制似乎無法可靠地工作。在C++靜態boost中保存python生成的值:: shared_ptr
通常情況下,我希望返回的boost::shared_ptr<>
擁有一個特殊的刪除程序來處理此問題,但似乎並非如此。看來發生的事情是,返回的boost::shared_ptr
只是包裝一個指向Python中產生的值的指針,而沒有任何特殊的刪除操作。這會導致來自雙重刪除(一個來自Python解釋器本身,一個來自C++靜態)的一致崩潰 - 或者至少看起來像它。
要使用下面的代碼重現此行爲,請創建一個test.cc
文件,並使用以下腳本進行測試。
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
struct A {
std::string _a;
A(std::string a): _a(a) {}
std::string str() { return _a; }
};
static boost::shared_ptr<A> holder(new A("foo"));
static void set_holder(boost::shared_ptr<A> a_ptr) {
holder = a_ptr;
}
static boost::shared_ptr<A> get_holder() {
return holder;
}
BOOST_PYTHON_MODULE(test)
{
using namespace boost::python;
class_<A, boost::shared_ptr<A> >("A", init<std::string>())
.def("__str__", &A::str)
;
def("set_holder", &set_holder);
def("get_holder", &get_holder);
}
隨着以下Python測試程序:
import test
print(str(test.get_holder()))
test.set_holder(test.A('bar'))
print(str(test.get_holder()))
編譯(與g++ -I/usr/include/python2.7 -shared -fpic test.cc -lboost_python -lpython2.7 -o test.so
)和Linux下運行上述程序(python test.py
)(ubuntu的12.10,與Python 2.7和Boost 1.50),導致以下堆棧跟蹤:
#0 0x000000000048aae8 in ??()
#1 0x00007fa44f85f589 in boost::python::converter::shared_ptr_deleter::operator()(void const*)() from /usr/lib/libboost_python-py27.so.1.50.0
#2 0x00007fa44fa97cf9 in boost::detail::sp_counted_impl_pd<void*, boost::python::converter::shared_ptr_deleter>::dispose()()
from /remote/filer.gx/home.active/aanjos/test.so
#3 0x00007fa44fa93f9c in boost::detail::sp_counted_base::release()()
from /remote/filer.gx/home.active/aanjos/test.so
#4 0x00007fa44fa9402b in boost::detail::shared_count::~shared_count()()
from /remote/filer.gx/home.active/aanjos/test.so
#5 0x00007fa44fa94404 in boost::shared_ptr<A>::~shared_ptr()()
from /remote/filer.gx/home.active/aanjos/test.so
#6 0x00007fa450337901 in __run_exit_handlers (status=0,
listp=0x7fa4506b46a8 <__exit_funcs>, run_list_atexit=true) at exit.c:78
#7 0x00007fa450337985 in __GI_exit (status=<optimized out>) at exit.c:100
#8 0x00007fa45031d774 in __libc_start_main (main=0x44b769 <main>, argc=2,
ubp_av=0x7fffaa28e2a8, init=<optimized out>, fini=<optimized out>,
rtld_fini=<optimized out>, stack_end=0x7fffaa28e298) at libc-start.c:258
#9 0x00000000004ce6dd in _start()
這表明在靜態析構函數中發生了雙重刪除。這種行爲似乎在不同平臺之間是一致的。
問題:是否可以實現描述的行爲而不復制boost::python
的返回值?在上面的玩具例子中,這很簡單,但在我真正的問題中,A
的深層複製是不切實際的。
感謝這個答案。這裏有很多信息,所以我需要一些時間來測試我的問題中的每一個。 –