用于声明具有别名的类层次结构的Cython语法

cls*_*udt 8 c++ python cython

这是一个抽象基类和一个具体的子类,我想通过Cython向Python公开:

class NodeDistance {

protected:
    const Graph& G;

public:
    NodeDistance(const Graph& G);
    virtual ~NodeDistance();
    virtual void preprocess() = 0;
    virtual double distance(node u, node v) = 0;
};


class NeighborhoodDistance: public NetworKit::NodeDistance {

public:
    NeighborhoodDistance(const Graph& G);
    virtual ~NeighborhoodDistance();
    virtual void preprocess();
    virtual double distance(node u, node v);
};
Run Code Online (Sandbox Code Playgroud)

这是我第一次尝试声明Cython类的接口.为了避免在cppclasses和Python包装器类之间发生命名冲突,我将每个声明Class为as _Class,然后是其正确的名称"Namespace::Class".

cdef extern from "../cpp/distmeasures/NodeDistance.h":
    cdef cppclass _NodeDistance "NetworKit::NodeDistance":
        _NodeDistance(_Graph G) except +
        void preprocess() except +
        double distance(node, node) except +


cdef extern from "../cpp/distmeasures/NeighborhoodDistance.h":
    cdef cppclass _NeighborhoodDistance(_NodeDistance) "NetworKit::NeighborhoodDistance":
        _NeighborhoodDistance(_Graph G) except +
        void preprocess() except +
        double distance(node, node) except +
Run Code Online (Sandbox Code Playgroud)

但是现在我在尝试表达它_NeighborhoodDistance的子类时遇到语法错误_NodeDistance.我做错了什么?

Error compiling Cython file:
------------------------------------------------------------
...
        void preprocess() except +
        double distance(node, node) except +


cdef extern from "../cpp/distmeasures/NeighborhoodDistance.h":
    cdef cppclass _NeighborhoodDistance(_NodeDistance) "NetworKit::NeighborhoodDistance":
                                                   ^
------------------------------------------------------------

_NetworKit.pyx:1698:52: Syntax error in C++ class definition
Run Code Online (Sandbox Code Playgroud)

Fre*_*Foo 2

我认为您甚至无法在 Cython 0.20.1 中表达基类和重命名的组合。您可以不重命名类并在以下位置指定命名空间cdef extern from

# C++ classes shown at the end
cdef extern from "example.hpp" namespace "example":
    cdef cppclass Base:
        void some_method() except +

    cdef cppclass Derived(Base):
        void some_method() except +
Run Code Online (Sandbox Code Playgroud)

...或者不指定继承:

cdef extern from "example.hpp" namespace "example":
    cdef cppclass Base "example::Base":
        void some_method() except +

    cdef cppclass Derived "example::Derived":
        void some_method() except +
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,Cython 似乎都没有完全理解 C++ 继承,并且您需要显式强制转换:

def test():
    cdef Derived d
    cdef Base *p = <Base *>&d
    p.some_method()
Run Code Online (Sandbox Code Playgroud)

这很丑陋,因为强制转换实际上关闭了 C++ 中的类型检查,但只要小心,它就可以安全地使用。(在其他情况下,Cython 的类型检查需要 C/C++ 中不需要的强制转换,这是非常不幸的。)

作为参考,以下是我使用的类:

// example.hpp
#include <cstdio>

namespace example {
    struct Base {
        virtual void some_method() = 0;
        virtual ~Base() = 0;
    };

    struct Derived {
        virtual void some_method()
        {
            std::puts("Hello!");
        }
        ~Derived()
        {
        }
    };
}
Run Code Online (Sandbox Code Playgroud)