关于C++:使用swig生成std :: vector到java.util.Vector代码

std::vector to java.util.Vector code generation with swig

我尝试用SWIG生成Java代码

在mylist.h中,我声明了一个名为"list"的自定义列表对象

1
List<T*> _list;

这个列表类继承自向量

1
class List : public vector<T>

在业务类(C++)中,我返回自定义对象的列表

1
2
3
4
List<MyObject> getMyList(){
   ....
   return list;
}

因此,我想生成Java代码,在这里我可以将这个C++列表检索为java. UTILIST或JavaUTL.Voice。

在我的swig.i文件中,我无法管理如何体现

1
2
3
4
%typemap(jstype) List"java.util.Vector"
namespace std {
   %template(CustomVector) vector<MyObject>;
}

任何帮助如何配置这个swig.i模板文件或一些示例代码来生成java.util.list/vector返回函数的方法都将得到赞赏。

谢谢您。


您不希望使用包装好的接口接触java.util.Vector,因为每次传入/传出函数时,您都会复制存储或进行大量复制操作。(也请注意,通常在C++中从容器中加入是奇特的设计)。

相反,在Java中,"正确"的事情是从EDCOX1(1)中继承。这个答案是我以前对一个类似问题的答案的一个更通用的版本。

它适用于所有std::vector类型,而不仅仅是固定类型,并处理需要通过使用"autobox"自定义类型映射的对象访问的原语。它缺少对专用std::vector的支持,但如果需要,可以简单地添加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
%{
#include <vector>
#include <stdexcept>
%}

%include <stdint.i>
%include <std_except.i>

namespace std {

    template<class T> class vector {
      public:
        typedef size_t size_type;
        typedef T value_type;
        typedef const value_type& const_reference;
        vector();
        vector(size_type n);
        vector(const vector& o);
        size_type capacity() const;
        void reserve(size_type n);
        %rename(isEmpty) empty;
        bool empty() const;
        void clear();
        void push_back(const value_type& x);
        %extend {
            const_reference get(int i) const throw (std::out_of_range) {
                return $self->at(i);
            }
            value_type set(int i, const value_type& VECTOR_VALUE_IN) throw (std::out_of_range) {
                const T old = $self->at(i);
                $self->at(i) = VECTOR_VALUE_IN;
                return old;
            }
            int32_t size() const {
              return $self->size();
            }
            void removeRange(int32_t from, int32_t to) {
              $self->erase($self->begin()+from, $self->begin()+to);
            }
        }
    };
}

// Java typemaps for autoboxing in return types of generics
%define AUTOBOX(CTYPE, JTYPE)
%typemap(autobox) CTYPE, const CTYPE&, CTYPE&"JTYPE"
%enddef
AUTOBOX(double, Double)
AUTOBOX(float, Float)
AUTOBOX(boolean, Boolean)
AUTOBOX(signed char, Byte)
AUTOBOX(short, Short)
AUTOBOX(int, Integer)
AUTOBOX(long, Long)
AUTOBOX(SWIGTYPE, $typemap(jstype,$1_basetype))

%typemap(javabase) std::vector"java.util.AbstractList<$typemap(autobox,$1_basetype::value_type)>"
%typemap(javainterface) std::vector"java.util.RandomAccess"
%typemap(jstype) std::vector get"$typemap(autobox,$1_basetype)"
%typemap(jstype) std::vector set"$typemap(autobox,$1_basetype)"
%typemap(jstype) std::vector &VECTOR_VALUE_IN"$typemap(autobox,$1_basetype)"
%typemap(javacode) std::vector %{
  $javaclassname(java.util.Collection<$typemap(autobox,$1_basetype::value_type)> e) {
    this.reserve(e.size());
    for($typemap(autobox,$1_basetype::value_type) value: e) {
      this.push_back(value);
    }
  }
%}

其中大部分与Swig目前提供的默认std_矢量非常相似,新的位是重命名、扩展和类型映射,扩展AbstractList和实现RandomAccess。它还添加了一个构造函数,它采用了其他EDCOX1×6的S——这是Java文档推荐的,而且很容易做到。(其他类型的std::vector有一个过载,速度快得多)。

我在另一个swig接口中测试了这个向量包装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
%module test

%include"vector.i"

%template(DblVec) std::vector<double>;
%template(ByteVec) std::vector<signed char>;
%include <std_string.i>
%template(StringVec) std::vector<std::string>;

%inline %{
struct foo {};
%}

%template(FooVec) std::vector<foo>;

我可以用它编译和运行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class run {
  public static void main(String argv[]) {
    System.loadLibrary("test");
    DblVec dv = new DblVec(100);
    for (int i = 0; i < 100; ++i) {
      dv.set(i,(double)i);
    }
    FooVec fv = new FooVec(1);
    fv.set(0, new foo());
    for (double d: dv) {
      System.out.println(d);
    }
  }
}