使用 swig 生成 std​​::vector 到 java.util.Vector 代码 [英] std::vector to java.util.Vector code generation with swig

查看:24
本文介绍了使用 swig 生成 std​​::vector 到 java.util.Vector 代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试用 SWIG 生成 java 代码

I try to generate java code with SWIG

MyList.h 中,我声明了一个名为 _list

In MyList.h I declared a custom list object called _list

List<T*> _list;

这个 List 类继承自 vector

and this List class inherits from vector

class List : public vector<T>

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

In a business class (in C++) I return a List of custom objects

List<MyObject> getMyList(){
   ....
   return list;
}

所以我想生成 java 代码,我可以在其中检索这个 C++ 列表作为 java.util.List 或 java.util.Vector.

so I want to generate java code where I can retrieve this C++ List as java.util.List or java.util.Vector.

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

in my swig.i file I couldn't manage how to embody

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

任何有关如何配置此 swig.i 模板文件或一些示例代码以生成 java.util.List/Vector 返回函数的帮助将不胜感激.

any kind help how to configure this swig.i template file or some sample code to generate a java.util.List / Vector returning function will be appreciated.

谢谢.

推荐答案

你真的不想用你包装的接口接触 java.util.Vector 因为你最终会重复存储或每次将其传入/传出函数时都会进行大量复制操作.(还要注意,通常在 C++ 中,从容器继承是奇怪的设计).

You don't really want to be touching java.util.Vector with your wrapped interfaces because you will end up duplicating storage or making large numbers of copy operations every time you pass it in/out of a function. (Note also that in general in C++ inhering from containers is odd design).

在 Java 中,正确"的做法是从 java.util.AbstractList 继承.这个答案是我对类似问题的旧答案的更通用版本.

Instead in Java the "right" thing to do is to inherit from java.util.AbstractList. This answer is a more generic version of my older answer to a similar question.

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

It works for all std::vector types, not just a fixed type and handles primitives which need to be accessed via Objects using an "autobox" custom type map. It's missing support for the specialized std::vector<bool>, but that should be simple to add if you need it.

%{
#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_vector.i 非常相似,新位是扩展 AbstractList 并实现 RandomAccess 的重命名、扩展和类型映射.它还添加了一个接受其他 Collection 的构造函数 - 这是 Java 文档推荐的并且很容易做到.(其他 std::vector 类型的重载快得多.

Most of this is fairly similar to the default std_vector.i that SWIG currently provides, the new bits are the renaming, extending and typemaps that extend AbstractList and implement RandomAccess. It also adds a constructor that takes other Collections - this is recommended by the Java documentation and easy enough to do. (There's an overload for other std::vector types which is much faster).

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

I tested this vector wrapping within another SWIG interface:

%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>;

我能够编译和运行:

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);
    }
  }
}

这篇关于使用 swig 生成 std​​::vector 到 java.util.Vector 代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆