6.12 传递和返回值类型

C++程序偶尔也会传递和返回对象的值类型。例如,可能有这样的函数:

  1. Vector cross_product(Vector a, Vector b);

如果没有Vector的信息,SWIG将会生成类似下面这样的包装函数:

  1. Vector *wrap_cross_product(Vector *a, Vector *b) {
  2. Vector x = *a;
  3. Vector y = *b;
  4. Vector r = cross_product(x,y);
  5. return new Vector(r);
  6. }

为了使包装代码得以编译通过,Vector必须定义拷贝构造函数也默认构造函数。

如果Vector在接口文件中定义了,但是不支持默认构造函数,SWIG会将用特殊的C++模板包装器封装参数,生成包装代码,这个过程称之为”富尔顿变换(Fulton Transform)”。生成的包装看起来像这样:

  1. Vector cross_product(Vector *a, Vector *b) {
  2. SwigValueWrapper<Vector> x = *a;
  3. SwigValueWrapper<Vector> y = *b;
  4. SwigValueWrapper<Vector> r = cross_product(x,y);
  5. return new Vector(r);
  6. }

译者注释:这段代码有点问题。我想应该是这样的:

  1. Vector *cross_product(Vector *a, Vector *b) {
  2. SwigValueWrapper<Vector> x = *a;
  3. SwigValueWrapper<Vector> y = *b;
  4. SwigValueWrapper<Vector> r = cross_product(x,y);
  5. return new Vector(r);
  6. }

这种转变有点鬼鬼祟祟,但是它支持值的传递,即使类没有提供默认构造函数,它让其他的SWIG自定特性得到合适的支持。SwigValueWrapper可以通过阅读SWIG生成的包装代码了解。这个类就是对指针做了一层薄的封装,其他什么都没做。

尽管SWIG一般探测类是否要这样应用富尔顿变换,但是在某些情况下有必要覆盖这个特性。可使用%feature("valuewrapper")%feature("novaluewrapper")开启或关闭此特性:

  1. %feature("novaluewrapper") A;
  2. class A;
  3. %feature("valuewrapper") B;
  4. struct B {
  5. B();
  6. // ....
  7. };

可以考虑为了那些有默认构造函数的类开启本特征。它将移除包装代码中在不变量声明处多余的构造函数调用,这将对大的对象和类生成更高性能的代码。另外一种方式是考虑返回引用或指针。

注意:这个转换对typemap或SWIG的其他部分没有作用——它应该是透明的,除非你看了SWIG的输出文件外。

注意:模板转换是SWIG-1.3.11新添加的,在将来的版本中可能重新定义。实践中,只有对没有定义默认构造函数的类才有决定对必要使用它。

注意:对这种模板的使用只有当对象通过传值传递参数或返回值时才发生。使用C++引用或指针的代码不会使用它。