Boost.Python:如何公开std :: unique_ptr

Boost.Python:如何公开std :: unique_ptr,第1张

Boost.Python:如何公开std :: unique_ptr

简而言之,Boost.Python不支持移动语义,因此不支持

std::unique_ptr
。Boost.Python的新闻/更改日志不表示已针对C
++
11移动语义进行了更新。此外,此功能要求为
unique_ptr
支持还未触碰了一年多。

尽管如此,Boost.Python支持通过来往于Python和从Python转移对象的专有所有权

std::auto_ptr
。从
unique_ptr
本质上来说
auto_ptr
,它是更安全的版本,因此将API改编成使用
unique_ptr
以下的API应该是相当简单的
auto_ptr

  • 当C 将所有权转让给Python时,C 函数必须:
    • 被暴露与CallPolicy
      boost::python::return_value_policy
      boost::python::manage_new_object
      结果转换器。
    • unique_ptr
      通过具有释放控制
      release()
      并返回原始指针
  • 当Python将所有权转让给C 时,C 函数必须:
    • 通过接受实例
      auto_ptr
      。在常见问题中提到,从C ++与返回的指针
      manage_new_object
      政策将通过进行管理
      std::auto_ptr
    • 对通孔具有
      auto_ptr
      释放控制
      unique_ptr``release()

给定一个无法更改的API /库:

/// @brief Mockup Spam class.struct Spam;/// @brief Mockup factory for Spam.struct SpamFactory{  /// @brief Create Spam instances.  std::unique_ptr<Spam> make(const std::string&);  /// @brief Delete Spam instances.  void consume(std::unique_ptr<Spam>);};

SpamFactory::make()
SpamFactory::consume()
需要经由辅助功能缠绕。

将所有权从C ++转移到Python的函数通常可以由创建Python函数对象的函数包装:

/// @brief Adapter a member function that returns a unique_ptr to///        a python function object that returns a raw pointer but///        explicitly passes ownership to Python.template <typename T,          typename C,          typename ...Args>boost::python::object adapt_unique(std::unique_ptr<T> (C::*fn)(Args...)){  return boost::python::make_function(      [fn](C& self, Args... args) { return (self.*fn)(args...).release(); },      boost::python::return_value_policy<boost::python::manage_new_object>(),      boost::mpl::vector<T*, C&, Args...>()    );}

lambda委托给原始函数,并将

releases()
实例的所有权委托给Python,并且调用策略表明Python将获取从lambda返回的值的所有权。,
mpl::vector
描述了Boost.Python的调用签名,从而使其能够正确管理语言之间的函数分配。

的结果显示

adapt_unique
SpamFactory.make()

boost::python::class_<SpamFactory>(...)  .def("make", adapt_unique(&SpamFactory::make))  // ...  ;

一般而言,适应

SpamFactory::consume()
比较困难,但是编写一个简单的辅助函数很容易:

/// @brief Wrapper function for SpamFactory::consume_spam().  This///        is required because Boost.Python will pass a handle to the///        Spam instance as an auto_ptr that needs to be converted to///        convert to a unique_ptr.void SpamFactory_consume(  SpamFactory& self,  std::auto_ptr<Spam> ptr) // Note auto_ptr provided by Boost.Python.{  return self.consume(std::unique_ptr<Spam>{ptr.release()});}

辅助函数将委托给原始函数,并将

auto_ptr
Boost.Python提供的函数转换
unique_ptr
为API所需的函数。的
SpamFactory_consume
辅助函数被公开为
SpamFactory.consume()

boost::python::class_<SpamFactory>(...)  // ... .def("consume", &SpamFactory_consume) ;

这是完整的代码示例:

#include <iostream>#include <memory>#include <boost/python.hpp>/// @brief Mockup Spam class.struct Spam{  Spam(std::size_t x) : x(x) { std::cout << "Spam()" << std::endl; }  ~Spam() { std::cout << "~Spam()" << std::endl; }  Spam(const Spam&) = delete;  Spam& operator=(const Spam&) = delete;  std::size_t x;};/// @brief Mockup factor for Spam.struct SpamFactory{  /// @brief Create Spam instances.  std::unique_ptr<Spam> make(const std::string& str)  {    return std::unique_ptr<Spam>{new Spam{str.size()}};  }  /// @brief Delete Spam instances.  void consume(std::unique_ptr<Spam>) {}};/// @brief Adapter a non-member function that returns a unique_ptr to///        a python function object that returns a raw pointer but///        explicitly passes ownership to Python.template <typename T,          typename ...Args>boost::python::object adapt_unique(std::unique_ptr<T> (*fn)(Args...)){  return boost::python::make_function(      [fn](Args... args) { return fn(args...).release(); },      boost::python::return_value_policy<boost::python::manage_new_object>(),      boost::mpl::vector<T*, Args...>()    );}/// @brief Adapter a member function that returns a unique_ptr to///        a python function object that returns a raw pointer but///        explicitly passes ownership to Python.template <typename T,          typename C,          typename ...Args>boost::python::object adapt_unique(std::unique_ptr<T> (C::*fn)(Args...)){  return boost::python::make_function(      [fn](C& self, Args... args) { return (self.*fn)(args...).release(); },      boost::python::return_value_policy<boost::python::manage_new_object>(),      boost::mpl::vector<T*, C&, Args...>()    );}/// @brief Wrapper function for SpamFactory::consume().  This///        is required because Boost.Python will pass a handle to the///        Spam instance as an auto_ptr that needs to be converted to///        convert to a unique_ptr.void SpamFactory_consume(  SpamFactory& self,  std::auto_ptr<Spam> ptr) // Note auto_ptr provided by Boost.Python.{  return self.consume(std::unique_ptr<Spam>{ptr.release()});}BOOST_PYTHON_MODULE(example){  namespace python = boost::python;  python::class_<Spam, boost::noncopyable>(      "Spam", python::init<std::size_t>())    .def_readwrite("x", &Spam::x)    ;  python::class_<SpamFactory>("SpamFactory", python::init<>())    .def("make", adapt_unique(&SpamFactory::make))    .def("consume", &SpamFactory_consume)    ;}

交互式Python:

>>> import example>>> factory = example.SpamFactory()>>> spam = factory.make("a" * 21)Spam()>>> spam.x21>>> spam.x *= 2>>> spam.x42>>> factory.consume(spam)~Spam()>>> spam.x = 100Traceback (most recent call last):  File "<stdin>", line 1, in <module>Boost.Python.ArgumentError: Python argument types in    None.None(Spam, int)did not match C++ signature:    None(Spam {lvalue}, unsigned int)


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5645926.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存