C++ 在Cython中优雅地包装模板对象
这类似于,但它从来没有得到任何解决方案,我至少有一个解决问题的办法,因为它是不雅观的 我试图包装一个模板类,C++ 在Cython中优雅地包装模板对象,c++,templates,pointers,dry,cython,C++,Templates,Pointers,Dry,Cython,这类似于,但它从来没有得到任何解决方案,我至少有一个解决问题的办法,因为它是不雅观的 我试图包装一个模板类,Point,其中\u T=int,float…和\u Scale是一个int。现在编译器将为使用的每个模板值生成一个单独的类,但这些类之间没有任何关联。但是,这些类共享它们的所有方法,主要是的运算符重载=*&/|,和getter 在Cython中,我能够包装点的唯一方法是为每个变体提供一个cdef类。它可以工作,但会产生大量复制粘贴的代码。我想知道是否有办法在这些模板类包装器之间共享代码。
Point
,其中\u T=int,float…
和\u Scale
是一个int。现在编译器将为使用的每个模板值生成一个单独的类,但这些类之间没有任何关联。但是,这些类共享它们的所有方法,主要是的运算符重载=*&/|代码>,和getter
在Cython中,我能够包装点的唯一方法是为每个变体提供一个cdef类。它可以工作,但会产生大量复制粘贴的代码。我想知道是否有办法在这些模板类包装器之间共享代码。请注意,我遵循教程中描述的cython包装方法,其中包装类将*thisptr
保存到它所包装的c对象
// c++ header
template<_T,__Scale>
class Point
{
Point(_T _x, _T _y) : x(_x), y(_y) {};
// copy constructor
template<typename _NT> Point(const Point<_NT, __Scale> &pt) : x( (_T)pt.x ), y( (_T)pt.y ) {};
_t x, y;
bool operator == (const Point<_T,__Scale> &pos) const
bool operator != (const Point<_T,__Scale> &pos) const
// and many more operators
}
typedef Point<int,1> PointA
typedef Point<int,8> PointB
... //additional typedefs
# cython interface with c++ (not shown: cdef extern from ...)
cdef cppclass Point[_T,__Scale]:
Point(_T _x, _T _y)
Point[_NT] Point(const Point[_NT,0] &pt)
_T x
_T y
bint operator == (const Point[_T,__Scale] &pos) const
bint operator != (const Point[_T,__Scale] &pos) const
# cython wrapper to interface with python (this is where it gets messy)
cdef class pyPointA:
cdef PointA* thisptr
def __cinit__(self, int x, int y):
self.thisptr = new PointA(x,y)
# everything in this class below this line is copied
def x(self, setX = None):
if(setX is None):
return self.thisptr.x
else:
self.thisptr.x = setX
def y(self, setY = None):
if(setY is None):
return self.thisptr.y
else:
self.thisptr.y = setY
# and many more operators
cdef class pyPointB
cdef PointB* thisptr
def __cinit__(self, int x, int y):
self.thisptr = new PointB(x,y)
# everything in this class below this line is copied
def x(self, setX = None):
if(setX is None):
return self.thisptr.x
else:
self.thisptr.x = setX
def y(self, setY = None):
if(setY is None):
return self.thisptr.y
else:
self.thisptr.y = setY
# and many more operators
...
#continue for additional point types
<代码> /C++头
模板
类点
{
点(_T_x,_T_y):x(_x),y(_y){};
//复制构造函数
模板点(const Point&pt):x((ut)pt.x),y((ut)pt.y){};
_tx,y;
布尔运算符==(常数点和位置)常数
布尔运算符!=(常数点和位置)常数
//还有更多的运营商
}
点A类型定义
类型定义点B
... //附加类型定义
Cython接口与C++(未示出:CDEF Extfrom from…)
cdef CPP等级点[\T,\u刻度]:
点(_T_x,_T_y)
点[\u NT]点(常数点[\u NT,0]&点)
_T x
_T y
bint运算符==(常量点[\T,\u刻度]&pos)常量
bint运算符!=(常数点[\T,\u刻度]&pos)常数
#cython包装器与python接口(这就是它变得混乱的地方)
cdef类pyPointA:
cdef PointA*此PTR
定义(自身、整数x、整数y):
self.thisptr=新点A(x,y)
#该类中此行下方的所有内容都将被复制
def x(自身,setX=无):
如果(setX为无):
返回self.thisptr.x
其他:
self.thisptr.x=setX
def y(自身,setY=无):
如果(setY为无):
返回self.thisptr.y
其他:
self.thisptr.y=setY
#还有更多的运营商
cdef类pyPointB
cdef点B*此PTR
定义(自身、整数x、整数y):
self.thisptr=新点B(x,y)
#该类中此行下方的所有内容都将被复制
def x(自身,setX=无):
如果(setX为无):
返回self.thisptr.x
其他:
self.thisptr.x=setX
def y(自身,setY=无):
如果(setY为无):
返回self.thisptr.y
其他:
self.thisptr.y=setY
#还有更多的运营商
...
#继续以获取其他点类型
以下是我尝试过的:
- 抽象cython基类以继承其他基类。好的,但是每个模板类型需要不同的指针
- 将
*此PTR
存储为*void
。如何处理铸件
- 通过使用getter
getPtr()
检索thisptr来封装它,但仍然强制使用单个返回类型。无法声明为Python函数,因为c指针不能包装在Python对象中
- 编写几个返回正确指针类型的方法,然后
getPtr()
方法为每个要调用的方法返回正确的getter,以从中获取指针。不幸的是,只有c函数可以返回指针,并且它们不能被返回:编译器抱怨“找不到”
- 与上面相同,只是
getPtr()
方法返回getter函数的字符串名,然后我们可以使用getattr()
调用该函数。但是在Python中无法使用getattr()
找到cdef方法
>这是一个困难,就是需要在C编译时实例化模板,当然C++中,对于不同的模板实例化,没有通用的“超类”。
在这种情况下,我通常建议使用jinja2之类的模板引擎来生成您感兴趣的类的所有排列。也许您需要这样做?我经历了这个问题,它似乎是编写Cython中的代码,将编译成C++,并与向量接口,但我想做一个能够从Python代码调用的包装类。@ Fr.FulbOOL:这不是现在称为A?不幸的是,我不认为不需要大量的工作/巧妙的技巧,就不会有一种完美无缝的方式将模板类公开给Python。这是因为Python根本没有类似于泛型的语言,因为根据动态类型语言的定义,一切都已经是“泛型的”。没有什么可以进行静态分析来确定要编译的类型实例化。您必须手动包装您打算在代码中使用的每个实例化类型,或者想出一种聪明的方法使实际类型在运行时不再需要。@flebool:如果您查看(在G++4.8版本中),那么您会看到红黑树(class
\u Rb\u tree\u node\u base
)的再平衡处理由预编译的非模板函数\u Rb\u tree\u insert\u和\u rebalance
提供。