如何使用 Cython 保持 C++ 类名不被修改?

Posted

技术标签:

【中文标题】如何使用 Cython 保持 C++ 类名不被修改?【英文标题】:How to keep a C++ class name unmodified with Cython? 【发布时间】:2012-04-11 22:12:43 【问题描述】:

我有一个名为 Foo 的 C++ 类。如果我遵循Cython C++ tutorial,我将需要以不同的方式调用 Python 类,例如 PyFoo。 但是我真的也需要调用 Python 类 Foo 。如何有效地做到这一点?

编辑:我正在尝试连接以前与 Boost Python 连接的现有 C++ 库。出于不同的原因,我想改为测试 Cython。 由于使用 Boost:Python Python 类的名称与 C++ 中的名称相同,因此我想继续使用此命名约定。以不同的方式调用类并不是 Python (CPython) 的要求,但它似乎是 Cython 强加的,至少在本教程中是这样。

我当然可以使用纯 python 模块来定义一个调用 PyFoo 的 Foo 类,但这看起来既无聊又低效。

【问题讨论】:

为什么不把 C++ 类改成 CppFoo 呢? 因为那样我还需要调用 Python 类 CppFoo... 是什么让你觉得PyFoo这个名字很特别?据我所知,唯一真正的要求是名称不同,唯一的原因是您将在 Python 类型的实现中引用 C++ 类型。 我编辑了我的问题,以便更清楚地了解我的目标。 为什么不拥有一个与 Cython 一起工作的模块,这样即使你对命名不满意,它也能正常工作,然后制作另一个作为外观的模块,除了类似'from _CppFoo 导入 *; Foo = PyFoo' 【参考方案1】:

有两种方法可以解决这个问题。

    用替代名称声明 C++ 类;原始名称必须用双引号指定:

    cdef extern from "defs.h" namespace "myns":
        cdef cppclass CMyClass "myns::MyClass":
            ...
    

    然后您可以将MyClass 用于您的python 类,并将C++ 声明称为CMyClass

    请注意,原始名称必须明确包含命名空间(如果它是命名空间的话)。 Cython 模板参数(如果存在)应该在备用名称声明之后。

    在单独的 .pxd 文件中声明您的 C++ 类,该文件的名称与您的 .pyx 文件不同,然后使用 cimport 导入它们。

    在 cpp_defs.pxd 中:

    cdef extern from "defs.h" namespace "myns":
        cdef cppclass MyClass:
            ...
    

    在 py_wrapper.pyx 中:

    cimport cpp_defs as cpp
    
    cdef class MyClass:
        cpp.MyClass *_obj
    

【讨论】:

对我来说,第二个选项抱怨在py_wrapper.pyx 中重新定义MyClass,尽管看起来cpp.MyClass 确实应该被视为一个单独的东西。第一个选项对我来说很好,尽管 namespace "myns" 必须在上一行,因为 cdef extern from "defs.h" namespace "myns": 或 cython 抱怨语法错误。 [使用 Cython 版本 0.20.1。] 函数有没有办法做到这一点? 函数有什么问题?文本覆盖(双引号)适用于所有 cdef 对象:类、函数、结构、typedef 等。将声明移动到单独的 .pxd(更自然的命名空间解决方案)也适用于所有对象。 @Mike 对于第二个选项,pyd 和 pyx 文件必须具有不同的名称。【参考方案2】:

这是一个完整的例子,展示了 Nikita 的方法:

cdef extern from "floorplan_geometry.h" namespace "flyby::localize":
    cdef cppclass CFloorplan "flyby::localize::Floorplan":
        int xmin()

cdef class Floorplan:
    cdef CFloorplan* obj_
    def __cinit__(self):
        self.obj_ = new CFloorplan()
    def __dealloc__(self):
        del self.obj_
    def xmin(self):
        return self.obj_.xmin()

【讨论】:

以上是关于如何使用 Cython 保持 C++ 类名不被修改?的主要内容,如果未能解决你的问题,请参考以下文章

Cython 中 C++ 函数的性能不佳

如何使用 cython 将 python 类公开给 c++

使用 Cython 时如何将一个 C++ 类(引用)传递给另一个?

如何在 Cython 中将 Python 对象转换为 C++ 类型

如何使用 Cython 向 Python 公开返回 C++ 对象的函数?

如何在 Cython 中使用不同的 C++ 编译器?