Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在Cython中优雅地包装模板对象_C++_Templates_Pointers_Dry_Cython - Fatal编程技术网

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
    提供。