Cython 和重载的 c++ 构造函数
Posted
技术标签:
【中文标题】Cython 和重载的 c++ 构造函数【英文标题】:Cython and overloaded c++ constructors 【发布时间】:2012-06-07 16:41:08 【问题描述】:是否有标准化(或普遍接受的方式)来解决包装 C++ 类时无法在 cython 中重载 __cinit__
方法的问题?
有可能使__cinit__
使用*args 和**kwargs 来包含参数,并在__cinit__
范围内根据特定模式选择生成C++ 实例的方式。然而,这种方法有一些复杂性:
__cinit__
参数列表中的类型调用时,它们将作为 Python 对象传递。在我的工作案例中,参数是 C++ 类的 Python 包装器,当它们作为 Python 对象从 *args 或 **kwargs 传递时,尝试检索这些实例“thisptr”是魔鬼的任务。
使用一系列 if...elif...else 案例从参数组合中选择 C++ 构造函数的隐含需求最终变得非常混乱。
所以必须有更好的方法。一种方法可能是使用 classmethod 方法(例如,参见:classmethod to overload __init__
behavior in Python)。尽管如此,据我所知(如果我错了,请纠正我),classmethod 意味着调用名称与类名不同的方法,这与 C++ 仅使用一个类名构造实例的方式不太相似。
对此有什么想法吗?
【问题讨论】:
【参考方案1】:就个人而言,我会使用类方法。
WrapperClass.fromSpambar(spambar)
这不是谜题恕我直言。如果您无法在 C++ 中重载函数,那么您也需要回退到这种方法。
如果您可以在初始化时接受一些繁重的操作,您可以通过定义“模式”或类似的方法来实现一种方法来识别调用构造函数的方式。 IE。 args 和 kwargs 的正则表达式。 ;)
我没有看到从 Python 对象获取 thisptr 的问题。
cdef WrapperClass wrpclsi
if isinstance(instance, WrapperClass):
wrpclsi = instance
else:
raise TypeError('expected instance of WrapperClass.')
cdef WrappedClassFromCpp* thisptr = wrpclsi.thisptr
【讨论】:
非常感谢 Niklas,是的,似乎解决这个问题的方法是使用类方法,这也将使处理参数类型的特定组合更安全。正则表达式可能会与类方法结合使用(例如,在给定参数类型组合的情况下选择特定的类方法构造函数,如果有意义的话)。 关于 thisptr 部分......是的,我认为这一点需要对我想说的内容有所了解。我的观点是,声明类似def __cinit__(self, PyKlass klass)
的内容在__cinit__
范围内调用klass.thisptr
不会有问题。然而,声明:def __cinit(self, *args)
假设在 args[0] 中有一个 PyKlass 实例,即使 args[0] 是 PyClass 类型的实例,调用 args[0].thisptr
也会有问题。事实证明,这没什么大不了的,只需在__cinit__
内进行转换即可解决,例如:klass = <PyClass?> args[0]
嗨 tachys。我实际上并没有谈论真正的正则表达式,只是一个使用类似机制但匹配 args 和 kwargs 的东西。与函数将传递的参数映射到它接受的参数的方式相同,您可以处理 args 和 kwargs 但允许多个调用约定。但是,这将涉及可能会大大减慢速度的处理。第二天我也许可以写一些示例代码。
没有将 Python 对象分配给 cdeffed 变量已经自动转换了吗?这就是我在上面的例子中所做的。 (暂时不能测试,上面的代码是从零开始的)
Niklas:谢谢,事实上,解析__cinit__
参数似乎是不可避免的,即使使用类方法(任何类方法最终都会求助于调用__cinit__
。我继续寻找最有效的方法来处理这个问题,希望很快就会发布.关于转换说明,如果参数作为 Python 对象传递(因为实例是参数列表的元素时),转换将是必要的(也就是说,为了清楚起见,如果参数未使用 'C' 类型传递)以上是关于Cython 和重载的 c++ 构造函数的主要内容,如果未能解决你的问题,请参考以下文章
C++类和对象(构造函数析构函数拷贝构造函数赋值运算符重载Const成员)详细解读
C++类和对象(构造函数析构函数拷贝构造函数赋值运算符重载Const成员)详细解读