Cython指针继承(Cython Pointer Inheritance)

编程入门 行业动态 更新时间:2024-10-28 12:16:54
Cython指针继承(Cython Pointer Inheritance)

问题

我有一个基类LinkPredictor和一个子类KatzIndex ,它派生自C++ LinkPredictor 。 现在我有另一个类,它在构造函数中需要一个指向LinkPredictor的指针。

我想在Cython包装这些类,使它们在Python可用。

我的尝试

CPP:

class LinkPredictor { ... }
class KatzIndex : public LinkPredictor { ... }
class KFoldCrossValidator {
public:
  KFoldCrossValidator(LinkPredictor* lp) { ... }
}

上面的方法不起作用。 Cython抛出以下错误消息:

Error compiling Cython file: ------------------------------------------------------------ ... cdef _KFoldCrossValidator* _this def __cinit__(self, LinkPredictor linkPredictor): self._this = new _KFoldCrossValidator(linkPredictor._this) ^ ------------------------------------------------------------ .../project.pyx:X:Y: Cannot convert Python object to '_LinkPredictor *'

Problem

I have a base class LinkPredictor and a sub class KatzIndex which derives from LinkPredictor in C++. Now I have another class which needs in its constructor a pointer to a LinkPredictor.

I want to wrap those classes in Cython to make them available in Python.

My try

CPP:

class LinkPredictor { ... }
class KatzIndex : public LinkPredictor { ... }
class KFoldCrossValidator {
public:
  KFoldCrossValidator(LinkPredictor* lp) { ... }
}

Question

The approach above is not working. Cython throws the following error message:

Error compiling Cython file: ------------------------------------------------------------ ... cdef _KFoldCrossValidator* _this def __cinit__(self, LinkPredictor linkPredictor): self._this = new _KFoldCrossValidator(linkPredictor._this) ^ ------------------------------------------------------------ .../project.pyx:X:Y: Cannot convert Python object to '_LinkPredictor *'

I think this happens because as _this is only declared in KatzIndex it has the type _KatzIndex* instead of _LinkPredictor*. Now I tried to declare the inheritance-relationship from _LinkPredictor and _KatzIndex (by declaring _KatzIndex(_LinkPredictor)) and hoped that Cython would accept _this with type _LinkPredictor* as _KatzIndex derives from _LinkPredictor. But that doesn't seem to be the case.

What are your thoughts on this?

最满意答案

你的问题是你的基类python包装器(LinkPredictor)需要包含一个指针成员,然后可以被派生类覆盖。

举个例子说我们正在包装以下c ++库:

foo.hpp

class Base {
public:
    virtual double a();
};

class Derived : public Base {
public:
    virtual double a();
};

class Using {
public:
    double a;
    Using(Base *b);
};
 

Foo.cpp中

#include "foo.hpp"

double Base::a()
{
    return 1.0;
}

double Derived::a()
{
    return 2.0;
}

Using::Using(Base *b) : a(b->a())
{}
 

然后我们可以将包装器写为

pyfoo.pyx

cdef extern from "foo.hpp":
    cdef cppclass Base:
        Base() except +

    cdef cppclass Derived(Base):
        Derived() except +

    cdef cppclass Using:
        Using(Base *b) except +
        double a

cdef class PyBase(object):
    cdef Base *_this
    def __cinit__(self):
        if type(self) != PyBase:
            return
        self._this = new Base()

    def __dealloc__(self):
        if self._this is not NULL:
            del self._this
            self._this = NULL

cdef class PyDerived(PyBase):
    def __cinit__(self):
        self._this = new Derived()

    def __dealloc__(self):
        if self._this is not NULL:
            del self._this
            self._this = NULL

cdef class PyUsing(object):
    cdef Using *_this
    def __cinit__(self, PyBase b):
        self._this = new Using(b._this)

    def a(self):
        return self._this.a

    def __dealloc__(self):
        if self._this is not NULL:
            del self._this
            self._this = NULL
 

除此之外,您可能还想阅读本教程

Your problem is that your python wrapper for the base class (LinkPredictor) will need to contain a pointer member which can then be overwritten by the derived classes.

As an example say we are wrapping the following c++ library:

foo.hpp

class Base {
public:
    virtual double a();
};

class Derived : public Base {
public:
    virtual double a();
};

class Using {
public:
    double a;
    Using(Base *b);
};
 

foo.cpp

#include "foo.hpp"

double Base::a()
{
    return 1.0;
}

double Derived::a()
{
    return 2.0;
}

Using::Using(Base *b) : a(b->a())
{}
 

We could then write the wrapper as

pyfoo.pyx

cdef extern from "foo.hpp":
    cdef cppclass Base:
        Base() except +

    cdef cppclass Derived(Base):
        Derived() except +

    cdef cppclass Using:
        Using(Base *b) except +
        double a

cdef class PyBase(object):
    cdef Base *_this
    def __cinit__(self):
        if type(self) != PyBase:
            return
        self._this = new Base()

    def __dealloc__(self):
        if self._this is not NULL:
            del self._this
            self._this = NULL

cdef class PyDerived(PyBase):
    def __cinit__(self):
        self._this = new Derived()

    def __dealloc__(self):
        if self._this is not NULL:
            del self._this
            self._this = NULL

cdef class PyUsing(object):
    cdef Using *_this
    def __cinit__(self, PyBase b):
        self._this = new Using(b._this)

    def a(self):
        return self._this.a

    def __dealloc__(self):
        if self._this is not NULL:
            del self._this
            self._this = NULL
 

In addition to this you might want to read through this tutorial

更多推荐

本文发布于:2023-08-07 21:12:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1465818.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:指针   Cython   Inheritance   Pointer

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!