我在C ++中有一个单例类(没有公共构造函数,C ++程序员调用class.instance()来创建单例或返回现有的单例)。
我更喜欢在Python级别隐藏它。如果我正在写一个Python单例,我会在__new__
中处理它。如果一个类没有公共构造函数,我认为我不能创建一个__init__
包装器(我的尝试失败了)。我在pybind11文档中没有提及__new__
(虽然可能错过了它,但Google似乎很乐意忽略包含“new”的返回页面,而没有提到__new__
)。
pybind11(甚至是Boost.Python)是否有单例配方?
答案 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