把我在實際過程中遇到的問題,總結一下,請先閱讀:python教程,python FAQ
1.如果封裝的c++類沒有拷貝建構函式怎麼辦?
定義class的時候,加入模板參數boost::noncopyable,同時指定no_init
- class_<ExpandEmitter,boost::noncopyable>("ExpandEmitter",no_init);
拷貝構造的目的是,c++對象執行個體傳遞給python時,可以通過拷貝構造重新構造一個python中使用的對象執行個體。一般如果沒有拷貝構造,需要boost的share_ptr來傳遞共用指標。
2.封裝的c++函數如何返回指標或者引用?
return_value_policy<return_by_reference>(),傳回值原則設定為return_by_reference即可
- .def("getPostData",&Request::getPostData,return_value_policy<return_by_reference>())
3.自訂的String怎麼和python進行自動轉換?
http://www.maycode.com/boostdoc/boost-doc/libs/python/doc/v2/faq.html#custom_string
struct template_string_to_python_str<br />{<br /> static PyObject* convert(TemplateString const& s)<br /> {<br /> return boost::python::incref(boost::python::object(s.ptr()).ptr());<br /> }<br />};</p><p>struct template_string_from_python_str<br />{<br /> template_string_from_python_str()<br /> {<br /> boost::python::converter::registry::push_back(<br /> &convertible,<br /> &construct,<br /> boost::python::type_id<TemplateString>());<br /> }</p><p> static void* convertible(PyObject* obj_ptr)<br /> {<br /> if (!PyString_Check(obj_ptr))<br /> {<br /> return 0;<br /> }<br /> return obj_ptr;<br /> }</p><p> static void construct(<br /> PyObject* obj_ptr, boost::python::converter::rvalue_from_python_stage1_data* data)<br /> {<br /> const char* value = PyString_AsString(obj_ptr);<br /> if (value == 0)<br /> boost::python::throw_error_already_set();<br /> void* storage = (<br /> (boost::python::converter::rvalue_from_python_storage<TemplateString>*)<br /> data)->storage.bytes;<br /> new (storage) TemplateString(value);<br /> data->convertible = storage;<br /> }<br /> };</p><p>BOOST_PYTHON_MODULE(ctemplate)<br />{<br /> boost::python::to_python_converter<<br /> TemplateString,<br /> template_string_to_python_str>();</p><p> template_string_from_python_str();<br />}
4.對象釋放的問題
假如在c++中建立的對象,在python中怎麼釋放?或者在python中建立的對象,在c++怎麼釋放?
我的看法是,在一種語言中建立並釋放。如果你想在python中建立對象,可以調用c++的函數,比如newClass()來建立,返回一個指標或者引用,使用完畢,調用c++的deleteClass()來釋放。否則,python引用計數會特別麻煩,很容易導致記憶體流失等問題。
5.共用指標,怎麼手工釋放?
共用指標,預設是自動釋放的,但是有時候,我們並不需要自動釋放,想自己手工釋放,可以定義一個釋放函數,在建立共用指標的時候,傳入釋放函數指標。
- //定義
- typedef boost::shared_ptr < World > world_ptr;
- //定義一個釋放函數
- void deleteWorld(World* w);
- //共用指標,傳入釋放函數指標
- world_ptr worldObjectPtr (new World,deleteWorld);
6.c++封裝模組,多個檔案include,怎麼會有多重定義的問題?
- BOOST_PYTHON_MODULE(hello)
- {
- class_ <World>("World")
- .def("greet", &World::greet)
- .def("set", &World::set)
- ;
- register_ptr_to_python <world_ptr>();
- }
如果上面這段在.h檔案中,多個cpp檔案引用是不行的。這個時候,可以定義一個標頭檔如下
- extern "C" void inithello();
你在標頭檔中首先聲明inithello(),在把上面的移到cpp中,BOOST_PYTHON_MODULE會實現一個函數inithello(),這樣就可以了。
7.如何封裝c++容器?
boost/python/suite/indexing目錄下的標頭檔
- //include
- #include <boost/python/suite/indexing/map_indexing_suite.hpp>
- //定義模組時,可以定義map
- //String map
- boost::python::class_<std::map<std::String,std::String> >("StrMap")
- .def(map_indexing_suite<std::map<std::String,std::String> >())
本人研究過一段時間並在實際項目中應用,寫出這個系列希望對大家有協助。
系列文章:
Python調用C/C++函數(1)
Python調用採用Boost Python封裝的c++(2)
C++調用Python(3)
C++調用Python(4)
c++和Python互操作進階應用程式(5)