我正在使用SWIG创建一些我无法更改的C ++代码的Python接口。其中一个C ++类有一个构造函数,它创建一个暂时无法使用的部分初始化对象,首先必须在其上调用初始化函数。我想在Python中通过提供一个替代构造函数来解决这个问题,该构造函数同时处理这两件事(获取和初始化)。让我们说在C ++中我有
class X {
public:
X() {...}
void init(T a) {...}
...
};
在C ++中,我必须将X实例化为
X x;
x.init(a);
在Python中我想做
x = X(a)
我的解决方案是一个hack,它取决于目标语言和SWIG生成包装器代码的具体方式:在我的.i文件中我有
%inline %{
X* new_X(T a) {
X* ret = new X();
ret->init(a);
return ret;
}
%nodefaultctor X;
class X {
public:
...
%extend {
%pythoncode {
def __init__(self, *args):
this = _modulename.new_X(*args)
try:
self.this.append(this)
except:
self.this = this
}
}
};
这种方法很好,但不是很令人满意:
这似乎是一个相对常见的用例,所以有人知道是否有标准方法吗?
答案 0 :(得分:2)
V-master的当前答案不能正常工作。但它可以起作用:
%ignore X::X();
// declaration of class X, e.g. %include X.h
%extend X {
X(T a) {
X* newX = new X();
newX->init(a);
return newX;
}
};
不可否认,这看起来有点可疑,但它确实有效,而且基本上是SWIG文档here中的一个例子。
重要的是要注意:
%extend适用于C和C ++代码。它不会以任何方式修改底层对象---扩展只出现在Python界面中。
所以这真正做的是创建一个方法(实际上甚至不是一个类方法),创建一个X
的新实例,在其上调用init(a)
并返回它。因为语法有点类似于构造函数,所以SWIG会将其包装起来。
答案 1 :(得分:1)
class studyInformationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('languages', 'collection', array('type' => new languageInformationType()))
;
}
这将隐藏默认的无参数构造函数并添加新的%ignore X::X();
%extend X {
X(T a) {
init(a);
}
};
缺点是如果忽略一个人正在做某事,那么你需要将其复制到这个新的,因为你不能从同一个类构造函数中调用其他构造函数(除非你使用的是C ++ 11)