如何使用pybind11包装单例类?

时间:2017-01-23 20:05:05

标签: pybind11

我在C ++中有一个单例类(没有公共构造函数,C ++程序员调用class.instance()来创建单例或返回现有的单例)。

我更喜欢在Python级别隐藏它。如果我正在写一个Python单例,我会在__new__中处理它。如果一个类没有公共构造函数,我认为我不能创建一个__init__包装器(我的尝试失败了)。我在pybind11文档中没有提及__new__(虽然可能错过了它,但Google似乎很乐意忽略包含“new”的返回页面,而没有提到__new__)。

pybind11(甚至是Boost.Python)是否有单例配方?

3 个答案:

答案 0 :(得分:1)

如果不从Python实例化您的类,则不需要公开__init__。至于你的问题,你可以尝试这样的事情:

py::class_<CppSingle>(mod, "Single")
.def_static("__new__", [](py:object) { return CppSingle::instance(); )},
 py::return_value_policy::reference_internal);

答案 1 :(得分:0)

我不确定pybind11,但我相信应该可以使用Boost.Python包装你的类。 (你的问题是&#34;甚至是Boost.Python&#34; ......)

使用noncopyable和/或no_init

class_<Klass, boost::noncopyable>("Klass", no_init)
    .staticmethod("instance")
    ;

https://mail.python.org/pipermail/cplusplus-sig/2004-March/006647.html

答案 2 :(得分:0)

假设您的单身人士课程如下:

class MySingleton{
    // private constructor here
public:
    MySingleton& instance();    
};

你可以把它包起来:

    py::class_<MySingleton, std::unique_ptr<MySingleton, py::nodelete>>(m, "MySingleton")
    .def(py::init([](){ 
        return std::unique_ptr<MySingleton, py::nodelete>>(&MySingleton::instance());
    });

这里的关键是使用py::nodelete所以不引用析构函数(当多个python实例使用的unique_ptrs被垃圾收集时,你的c ++单例不会被破坏)。

该代码还依赖于pybind11 v2.2.0(2017年8月31日)引入的自定义构造函数支持,它允许我们在init中包装lambda而不是构造函数。

参考
  - Pybind11 v2.2.0 changelog
  - Pybind11 doc about custom constructors
  - Pybind11 doc on non-public destructors