element typemap + stl_vector.i typemap + ??? - >包裹功能列出的元素

时间:2014-07-27 10:19:43

标签: c++ swig

假设我有一个任意的非平凡类型A,我可以为其编写类型图。特别是,假设我知道如何将std::strings转换为A,并且我将目标语言中的字符串打印到A。我导入stl_vector.i%template(AVector) std::vector<A>;

SWIG中最快/最简单(甚至是'正确')的操作方法是使用void func(const std::vector<A>& vals)的函数包装器,其中目标语言端的预期输入是字符串列表(例如{{在Python中1}}?除非我错了,否则Just Work™似乎没有(具体来说,在生成的包装器代码中我没有看到['a', 'qqq']的类型映射代码)。

如果需要特定的目标语言来回答,那就说它是Python。我宁愿能够在一般情况下这样做,但是......

1 个答案:

答案 0 :(得分:0)

假设我们有一个类似的头文件:

#ifndef TEST_H
#define TEST_H

#include <iostream>
#include <functional>
#include <iterator>

struct A {
  A(const std::string& v) : val(v) {}
  A(const A&) = default;
  A() = default;
  std::string val;
};

inline std::ostream& operator<<(std::ostream& in, const A& o) {
  return in << o.val;
}

inline void run(const std::vector<A>& in) {
  std::copy(in.begin(), in.end(), std::ostream_iterator<A>(std::cout, "\n"));
}    
#endif

我们希望将其包装起来,以便可以使用字符串列表调用run,或者可以互换地调用std::vector<A>

鉴于语言不可知论是一个明确的目标,实现这一目标的最佳方法是引入更多的C ++,以帮助进行某些类型的转换和过载。

我们最初可以用以下简单的方式包装头文件:

%module test

%include <std_vector.i>
%include <std_string.i>

%{
#include "test.h"
%}

%template(AVec) std::vector<A>;

%include "test.h"

这足以运行Python测试用例的前半部分:

import test

test.A("")

v1=test.AVec(2,test.A("testing"))
print type(v1)
test.run(v1)

# Here onwards needs some more work though...
v2=["hello", "world", "isn't", "this", "fun"]
print type(v2)
test.run(v2)

要开始使用此测试用例的后半部分,我们需要调整SWIG接口。我将通过在包装器内部添加一个函数以及利用SWIG的std::vector<std::string>默认类型映射的重载来实现此目的。

添加:

%{
// Some glue to trivially convert types
std::vector<A> convert(const std::vector<std::string>& in) {
  std::vector<A> ret;
  std::copy(in.begin(), in.end(), std::back_inserter(ret));
  return ret;
}
%}

%inline %{
// An overload.
void run(const std::vector<std::string>& in) {
  run(convert(in));
}
%}

在初始SWIG界面的末尾,我们添加了一个有效的重载,只要目标语言对std::vector有一个合适的理解。 (我检查的大多数似乎都是。)

对于SWIG版本,我测试了这个版本,运行SWIG本身并打开警告,发出了关于阴影过载的(虚假)警告。这个警告似乎是不正确的,因为生成的代码确实根据给定的参数选择了正确的重载。

在接口文件中使用添加了%inline的重载是迄今为止最快/最简单的方法来启动和运行。它当然需要复制/转换开销每个函数手动写入重载。使用类型映射执行此操作只需要编写单个类型映射,但很难以独立于目标语言的方式执行。