用 cython 包装一个 c++ 单例

Wrapping a c++ singleton with cython

使用 Cython 将某些部分从 C++ API 包装到 python,我遇到了无法通过搜索类似问题解决的误解。我喜欢访问具有私有构造函数和 public 方法 GetInstance.

的工厂 class
namespace cpplibrary
{
    class CppFactory
    {
    public:
        static CppFactory& GetInstance();
    private:
        CppFactory(void);
        CppFactory( const CppFactory& );
    };
}

我正在尝试像这样的 cython 代码:

cdef extern from "cppFactory.h" namespace "cpplibrary":
    cdef cppclass CppFactory:
        CppFactory() except +
        CppFactory& GetInstance()

cdef class PyFactory:
    cdef CppFactory* _thisptr
    def __cinit__(self):
        self._thisptr = GetInstance()

我检查了尽可能多的变体。在 extern 中有和没有构造函数的声明。使用不同的方式从不同的已发布示例中定义 _thisptr。等等。但是我找不到像这样的单例示例。

我看不到错误在哪里?

我认为你有两个问题:

1)如何包装静态方法:the recommended way就是在class外面声明函数,用一个字符串告诉Cython在C++中应该用什么名字

2) 对 thisptr 的赋值,您只需要使用 & 从引用中获取指针。

代码:

cdef extern from "cppFactory.h" namespace "cpplibrary":
    cdef cppclass CppFactory:
        CppFactory() except +

    # declare outside the class and use a string to specify name
    # unfortunately this doesn't seem to play well with namespace
    # so we need to specify it again
    cdef CppFactory& CppFactory_GetInstance "cpplibrary::CppFactory::GetInstance"()

cdef class PyFactory:
    cdef CppFactory* _thisptr
    def __cinit__(self):
        self._thisptr = &CppFactory_GetInstance()

问题之一确实是包装静态方法(此处Getinstance())。

你可以通过使用 cython @staticmethod 装饰器来做到这一点(参见 Cython 的文档 here):

cdef extern from "cppFactory.h" namespace "cpplibrary":
    cdef cppclass CppFactory:
        @staticmember
        CppFactory& GetInstance()

那么,.pyx 可以是:

cdef class PyFactory:
    cdef CppFactory* _thisptr
    def __cinit__(self):
        self._thisptr = new CppFactory()