c++和Python互操作高级应用(5)

把我在实际过程中遇到的问题,总结一下,请先阅读:python教程,python FAQ

1.如果封装的c++类没有拷贝构造函数怎么办?
定义class的时候,加入模板参数boost::noncopyable,同时指定no_init

  1.  class_<ExpandEmitter,boost::noncopyable>("ExpandEmitter",no_init);

拷贝构造的目的是,c++对象实例传递给python时,可以通过拷贝构造重新构造一个python中使用的对象实例。一般如果没有拷贝构造,需要boost的share_ptr来传递共享指针。

2.封装的c++函数如何返回指针或者引用?
return_value_policy<return_by_reference>(),返回值策略设置为return_by_reference即可

  1.  .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

 

[cpp]  view plain copy
  1. struct template_string_to_python_str  
  2. {  
  3.     static PyObject* convert(TemplateString const& s)  
  4.     {  
  5.         return boost::python::incref(boost::python::object(s.ptr()).ptr());  
  6.      }  
  7. };  
  8.    
  9. struct template_string_from_python_str  
  10. {  
  11.     template_string_from_python_str()  
  12.     {  
  13.         boost::python::converter::registry::push_back(  
  14.                 &convertible,  
  15.                 &construct,  
  16.                 boost::python::type_id<TemplateString>());  
  17.     }  
  18.   
  19.     static void* convertible(PyObject* obj_ptr)  
  20.     {  
  21.         if (!PyString_Check(obj_ptr))  
  22.         {  
  23.             return 0;  
  24.         }  
  25.         return obj_ptr;  
  26.     }  
  27.    
  28.     static void construct(  
  29.         PyObject* obj_ptr,             boost::python::converter::rvalue_from_python_stage1_data* data)  
  30.       {  
  31.           const char* value = PyString_AsString(obj_ptr);  
  32.           if (value == 0)  
  33.               boost::python::throw_error_already_set();  
  34.           void* storage = (  
  35.               (boost::python::converter::rvalue_from_python_storage<TemplateString>*)  
  36.               data)->storage.bytes;  
  37.           new (storage) TemplateString(value);  
  38.           data->convertible = storage;  
  39.       }  
  40.  };  
  41.   
  42. BOOST_PYTHON_MODULE(ctemplate)  
  43. {  
  44.     boost::python::to_python_converter<  
  45.         TemplateString,  
  46.         template_string_to_python_str>();  
  47.   
  48.      template_string_from_python_str();  
  49. }  


4.对象释放的问题
假如在c++中创建的对象,在python中怎么释放?或者在python中创建的对象,在c++怎么释放?
我的看法是,在一种语言中创建并释放。如果你想在python中创建对象,可以调用c++的函数,比如newClass()来创建,返回一个指针或者引用,使用完毕,调用c++的deleteClass()来释放。否则,python引用计数会特别麻烦,很容易导致内存泄漏等问题。

5.共享指针,怎么手工释放?
共享指针,默认是自动释放的,但是有时候,我们并不需要自动释放,想自己手工释放,可以定义一个释放函数,在创建共享指针的时候,传入释放函数指针。

  1. //定义
  2. typedef boost::shared_ptr < World > world_ptr;
  3. //定义一个释放函数
  4. void deleteWorld(World* w);
  5. //共享指针,传入释放函数指针
  6. world_ptr worldObjectPtr (new World,deleteWorld);

6.c++封装模块,多个文件include,怎么会有多重定义的问题?

  1. BOOST_PYTHON_MODULE(hello)
  2. {
  3.       class_ <World>("World")
  4.           .def("greet", &World::greet)
  5.           .def("set", &World::set)
  6.       ;
  7.       register_ptr_to_python <world_ptr>();
  8. }

如果上面这段在.h文件中,多个cpp文件引用是不行的。这个时候,可以定义一个头文件如下

  1. extern "C" void inithello();

你在头文件中首先声明inithello(),在把上面的移到cpp中,BOOST_PYTHON_MODULE会实现一个函数inithello(),这样就可以了。

7.如何封装c++容器?
boost/python/suite/indexing目录下的头文件

  1. //include
  2. #include <boost/python/suite/indexing/map_indexing_suite.hpp>
  3. //定义模块时,可以定义map
  4.    //String map
  5.     boost::python::class_<std::map<std::String,std::String> >("StrMap")
  6.         .def(map_indexing_suite<std::map<std::String,std::String> >())


本人研究过一段时间并在实际项目中应用,写出这个系列希望对大家有帮助。

转自:http://blog.csdn.net/marising/article/details/2962560

你可能感兴趣的:(c++和Python互操作高级应用(5))