gpt4 book ai didi

python - cython c++类继承无法实例化派生类

转载 作者:搜寻专家 更新时间:2023-10-31 02:09:40 25 4
gpt4 key购买 nike

我正在尝试用 Cython 包装一些 C++ 类。对于基类,一切正常。对于具有与其各自基类相同参数(在其构造函数中)的派生类,也会发生同样的情况。但是,我无法实例化与其基类具有不同数量参数(在其构造函数中)的派生类。

例如:

  • h文件
// CYH.h file
#ifndef __CYH_H__
#define __CYH_H__

#include <iostream>

class Base
{
public:
Base(double);
~Base();
double A;
double getA();
void setA(double);
};

class Derived : public Base
{
public:
Derived(double, double);
~Derived();

double B;
};
#endif
  • cpp文件
// cyh.cpp file
#include <iostream>
#include <string>
#include "include/cyh.h"

Base::Base(double a)
{
A = a;
}

Base::~Base()
{
}

double Base::getA(){
return A;
}

void Base::setA(double a_){
A = a_;
}

Derived::Derived(double a, double b) : Base(a)
{
B = b;
}

Derived::~Derived()
{
}
  • 和pyx文件
cdef extern from "include/cyh.h":
cdef cppclass Base:
Base(double)
double getA()
void setA(double)

cdef cppclass Derived(Base):
Derived(double, double)

cdef class cyBase:
cdef Base *thisptr
def __cinit__(self, double a):
if type(self) is cyBase:
self.thisptr = new Base(a)

def __dealloc__(self):
if type(self) is cyBase:
del self.thisptr

@property
def A(self):
return self.thisptr.getA()

@A.setter
def A(self, value):
self.thisptr.setA(value)


cdef class cyDerived(cyBase):
cdef Derived *thisptrDerived
def __cinit__(self, double a, double b):
if type(self) is cyDerived:
self.thisptrDerived = self.thisptr = new Derived(a, b)

def __dealloc__(self):
if type(self) is cyDerived:
del self.thisptrDerived

它编译并且 pyd 构建成功。但是,当我尝试使用以下方法实例化 cyDerived 类时:

mycyObj = cyDerived(a=2., b=3.)

我收到以下错误:

__cinit__() got an unexpected keyword argument 'b'

Ant 知道我做错了什么?

非常感谢!

最佳答案

其实这是一个很有趣的问题:使用*args**kwargs的性能损失是多少,应该考虑哪些场景?

从理论的角度来看,如果*args ,使用**kwargs解决方案:

  1. 获取指向argskwargs 的指针并在垃圾收集器中注册这些引用,
  2. 查字典(一些开销),
  3. 当不再需要时,注销垃圾收集器中的引用,以便销毁该字典。

我的假设是,注册/取消注册可能是个问题,因为引用更新需要获取 GIL。最好不要经常这样做。

没有 *args 的解决方案似乎能够在不需要更改引用计数器的情况下工作。

到目前为止我的理论,但我希望看到一些实证结果,这可能会非常令人惊讶,所以如果您有一些数据,请与我们分享。


重现我的结果的代码:

#no_kwargs.pyx:
cdef class cyBase:
def __cinit__(self, double a):
pass

cdef class cyDerived:
def __cinit__(self, double a):
self.a=a


#kwargs.pyx
cdef class cyBase:
def __cinit__(self, *argv, **kwargs):
pass

cdef class cyDerived:
def __cinit__(self, double a):
self.a=a

运行它

python -m cython XXX.pyx 

并比较生成的 c 文件。主要区别在于 cyBase::__cinit__() 整个引用计数发生的地方:

static int __pyx_pw_4test_6cyBase_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
...
__Pyx_INCREF(__pyx_args); // <----------- HERE
__pyx_v_argv = __pyx_args;
...

/* function exit code */
__Pyx_XDECREF(__pyx_v_argv); // <----------- HERE
...
return __pyx_r;
}

kwargs 这里好像没用到。

关于python - cython c++类继承无法实例化派生类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46342971/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com