在 Cython 中优雅地包装模板化对象
Wrapping templated objects elegantly in Cython
这类似于这个问题,但它从未得到任何解决方案,我至少有一个解决这个问题的方法,尽管它很不优雅。
我正在尝试包装一个模板化类,Point<_T,__Scale>
,其中 _T=int,float...
和 __Scale
是一个 int。现在,编译器将为使用的每个模板值生成一个单独的类,但这些类没有任何关系。但是,这些类共享它们的所有方法,主要是!=<>*&/|
和getter的运算符重载。
在 Cython 中,我能够包装Point<_T,__Scale>
的唯一方法是为每个变体提供一个 cdef 类。它可以工作,但会导致大量复制粘贴的代码。我想知道是否有办法在这些模板类包装器之间共享代码。请注意,我遵循教程中描述的 cython 包装方法,其中包装类保存它正在包装的 c 对象的*thisptr
。
// 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
这是我尝试过的:
- 抽象的cython基类,从中继承其他基类。好的,但是每种模板类型都需要不同的指针。
- 将
*thisptr
存储为*void
。如何应对选角? - 通过使用 getter
getPtr()
检索来封装thisptr
,但仍然强制为单个返回类型。不能声明为 Python 函数,因为 c 指针不能包装在 python 对象中。 - 编写几个返回正确指针类型的方法,然后
getPtr()
方法为每个要调用的方法返回正确的 getter,以便从中获取指针。不幸的是,只有 c 函数可以返回指针,并且它们不能返回:编译器抱怨"未找到"。 - 与上面相同,除了
getPtr()
方法返回 getter 函数的字符串名称,然后我们可以使用它getattr()
来调用。但是cdef方法无法使用getattr()
在Python中找到。
这样做的困难在于模板需要在 C 编译时实例化......当然,在C++中,各种模板实例化没有通用的"超类"。
通常,在这种情况下,我建议使用模板引擎(例如 jinja2(来生成您感兴趣的类的所有排列。
相关文章:
- 包装一个对象并假装它是一个 int
- 错误:"释放后使用包装器对象 (WRAPPER_ESCAPE)"
- C++包装库:在堆栈上分配C++ C 中的对象
- 将对象传递给函数而不将其包装到 std::ref 中,而参数被指定为 const 引用
- 在 C++ 对象包装器中安全地包含 C 代码
- 如何将 c++ 类包装到 python 中,以便我可以使用 pybind11 访问其成员的公共方法(成员是一个对象指针)
- 在 C++ 中为 C 样式对象创建一个透明包装类
- 如何将包装类的对象用作包装函数中的参数
- 如何包装对象,使它们成为无法交互的单独类型?
- 由 pybind11 包装的对象的内存开销
- 将抽象值对象保存在包装器中和继承的用法中
- 将numpy对象传递到Pythonqt包装器
- 如何将 Python 中的字节对象传递给用 Swig 包装的C++函数
- 将 C 对象的数组包装到类C++
- 泛型对象包装器
- OpenGL对象包装器中的自动绑定
- 如何编写安全的原子对象包装器?
- 我的GLSL着色器对象/包装器是否应该封装加载/设置VertexArrayObject
- 将C++对象包装在外部“C”中
- 移动值/对象包装器的构造函数