У меня проблема с использованием Cython конструкторов по умолчанию.
Мой класс C ++ Node следующий
Node.h
class Node
{
public:
Node()
{
std::cerr << "calling no arg constructor" << std::endl;
w=0.0;
d=0.0;
}
Node(double val, double val2);
{
std::cerr << "calling 2 args constructor" << std::endl;
this->w=val;
this->d=val2;
}
private:
double d,w;
}
завернут в Cython следующим образом
cdef extern from "Node.h":
cdef cppclass Node:
Node() except +
Node(double val1, double val2) except +
double d
double w
cdef class pyNode:
cdef Node *thisptr # hold a C++ instance which we're wrapping
def __cinit__(self):
self.thisptr = new Node()
def __cinit__(self, double val1, double val2):
self.thisptr = new Node(val1,val2)
def __dealloc__(self):
del self.thisptr
def __repr__(self):
return "d=%s w=%s" % (self.thisptr.w, self.thisptr.w )
Код Cython хорошо компилируется, но особенно при вызове из Python
from pyNode import pyNode as Node
n=Node(1.0,2.0)
Я получил ожидаемое calling 2 args constructor
строка, но если я пытаюсь объявить объект Node из python, используя конструктор «no-arguments» (который должен быть правильно объявлен как __cinit__(self)
Я не получаю вывод, это означает, что конструктор без аргументов не вызывается!
Как я могу явно назвать это из CInit метод обернутого класса?
Проблема в том, что вы не можете перегрузить __cinit__()
так (как только cdef
функции могут быть перегружены) — вместо этого, пусть он принимает значения по умолчанию, а затем вызывает нужную вещь по мере необходимости.
Редактировать: По сути, вам нужно реализовать эту функцию в большей степени, чем в обычном коде Python, вместо использования перегрузки:
def __cinit__(self, double val1=-1, double val2=-1):
if val1 == -1 or val2 == -1:
self.thisptr = new Node()
else:
self.thisptr = new Node(val1,val2)
Естественно, это предполагает -1
это значение, которое бесполезно для функции, вы можете использовать другое значение, или если вам нужно, чтобы каждое значение типа double было допустимым, тогда вам может потребоваться удалить типизацию, взяв объект Python, чтобы вы могли использовать None
по умолчанию:
def __cinit__(self, val1=None, val2=None):
if val1 is not None and val2 is not None:
self.thisptr = new Node(val1, val2)
else:
self.thisptr = new Node()
Других решений пока нет …