Cython:python类包装器中的模板

pio*_*ocz 11 c++ python templates cython

有没有办法为包含模板的Cython包装的C++类创建Python包装器?(即完全按照此处显示但使用模板:http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#create-cython-wrapper-class).

我知道融合类型的变通方法(https://groups.google.com/forum/#!topic/cython-users/qQpMo3hGQqI),但是这不允许你实现类似的类vector<vector<int>>:融合类型具有,毫不奇怪,没有递归的概念.

改写

我想要实现的是一个包装类,如:

cdef extern from "header.h":
    cdef cppclass Foo[T]:
        Foo(T param)
        # ...
Run Code Online (Sandbox Code Playgroud)

创建一个简单的Python包装器:

cdef class PyFoo[T]:  # I know the '[T]' can't be here, it's a wish
    cdef Foo[T] *thisptr
    def __cinit__(self, param):
        self.thisptr = new Foo[T](param)
    # ...
Run Code Online (Sandbox Code Playgroud)

我很确定Cython本身并不支持,但也许有人可以想到一个解决方法.我不是在寻找惯用的或好的例子,我只是想知道这是否可行.

Dav*_*idW 8

正如你所说,Cython并不真正支持这一点.

我认为到目前为止最简单的方法是使用字符串替换手动生成一堆Cython文件.从"foowrapper.pxi.src"文件(您希望的名称......)开始:

cdef class PyFoo_{T}:
  cdef Foo[{T}] *thisptr
  def __cinit__(self, param):
    self.thisptr = new Foo[{T}](param)
    # etc
Run Code Online (Sandbox Code Playgroud)

接下来,通过一个简单的程序(也可能是Python)运行它来加载文件,执行字符串替换,并以新名称再次保存文件.关键是:

output = code.format(T=T) # where T is a string with a C++ class name 
              # e.g. "int" or "std::vector<double>"
Run Code Online (Sandbox Code Playgroud)

(显然有一些与加载和保存相关的代码,我已经跳过了懒惰)

然后,在您的Cython文件中,您只需"包含"每个类的生成文件.Cython中的"include"命令是一个文字文本包含(如C预处理器),并期望一个.pxi文件:

cdef extern from "header.h":
    cdef cppclass Foo[T]:
        Foo(T param)
        # ...

include "foowrapper_int.pxi"
include "foowrapper_vectordouble.pxi
# etc
Run Code Online (Sandbox Code Playgroud)

您必须选择要在编译时生成的类,但这是不可避免的(模板是编译时功能),因此您永远无法从Python脚本环境动态生成它们,因为相应的C++类赢了不会被生成.

其他选择

其他几个选项值得简要考虑.首先,您可以继承Foo<T>一个FooBase不依赖于模板参数的基类(比如说).然后你将包装FooBase在Cython中(为你关心的案例生成类似构造函数的函数).如果要调用的函数没有依赖于模板类型的参数,那么这才真正可行.显然,这也涉及更改C++代码.

部分选项是查看不同的包装方式.Boost Python肯定会支持这种本地(但它有自己的缺点).我想SIP/SWIG也会应付(但我不知道).如果需要,您可以将这些与Cython进行相当干净的混合匹配(通过导入包含模板类的生成模块).