4

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

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

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

4

3 回答 3

2

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

py::class_<CppSingle>(mod, "Single")
.def_static("__new__", [](py:object) { return CppSingle::instance(); )},
 py::return_value_policy::reference_internal);
于 2017-04-03T18:34:25.540 回答
2

假设你的单例类看起来像这样:

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 变更日志
- Pybind11 文档关于自定义构造函数
- Pybind11 文档关于非公共析构函数

于 2018-05-29T20:39:10.357 回答
0

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

使用noncopyable和/或no_init

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

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

于 2017-03-15T17:45:10.883 回答