6

SWIGでJavaコードを生成しようとしています

MyList.hで、_listというカスタム リスト オブジェクトを宣言しました。

List<T*> _list;

そして、この List クラスは vector から継承します

class List : public vector<T>

ビジネス クラス (C++) では、カスタム オブジェクトのリストを返します。

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

そのため、この C++ リストを java.util.List または java.util.Vector として取得できる Java コードを生成したいと考えています。

私のswig.iファイルでは、具体化する方法を管理できませんでした

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

この swig.i テンプレート ファイルまたはいくつかのサンプル コードを構成して、java.util.List / Vector を返す関数を生成する方法についてのヘルプをいただければ幸いです。

ありがとうございました。

4

1 に答える 1

10

java.util.Vector関数に出入りするたびにストレージを複製したり、多数のコピー操作を行ったりすることになるため、ラップされたインターフェイスに触れたくはありません。(一般に、C ++ではコンテナーからの継承は奇妙な設計であることに注意してください)。

代わりに、Javaで行うべき「正しい」ことは、から継承することですjava.util.AbstractListこの回答は、同様の質問に対する私の古い回答のより一般的なバージョンです。

std::vector固定タイプだけでなく、すべてのタイプで機能し、「オートボックス」カスタムタイプマップを使用してオブジェクトを介してアクセスする必要があるプリミティブを処理します。専用のサポートstd::vector<bool>がありませんが、必要に応じて簡単に追加できます。

%{
#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タイプには、はるかに高速な過負荷があります)。

このベクトルラッピングを別のSWIGインターフェイス内でテストしました。

%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);
    }
  }
}
于 2012-09-23T09:18:08.260 に答える