は、Javaマップ、唯一std::vector
にC++でstd::list
のための実装はありません3.0.8。これはほとんどの場合にはあまり理想的ではないので、SWIGの定義をstd::list
にすることが可能かどうか、どうすればいいでしょうか?std :: listのtypemapをどのように作成しますか?SWIGのC++とJavaのリスト<String>への<std::string>は? SWIGで
答えて
私はJavaでうまくstd::list
を包むために働く必要があるタイプマップのセットを書きました。それらは基本クラスとしてjava.util.AbstractSequentialList
を使用するので、存在するデータのコピーは1つしかなく、JavaとC++の両方のデータ構造としてうまく機能します。この答えは、私がan older answer wrapping std::vector
で使ったのと同じ手法の改良と港です。私は今それを非常に多くを再利用していますので、
は、まず私は、私の古い答えの出てスタンドアロンのファイルにautobox.i「をAutoBoxの」タイプマップを引っ張っ:
// 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))
をそれから私は私の中でこれを使用しました以下std_list.iファイル:
%include <autobox.i>
%include <stdint.i>
%{
#include <list>
#include <algorithm>
%}
namespace std {
template <typename T> class list {
public:
// This typedef is a weird hack to make stuff work
typedef std::list<T>::iterator iterator;
typedef size_t size_type;
typedef T value_type;
typedef T& reference;
void assign(size_type n, const value_type &val);
bool empty() const;
list(size_type n, const value_type &value=value_type());
list(const list &o);
list();
~list();
size_type max_size() const;
void pop_back();
void pop_front();
void push_back(const value_type &x);
void push_front(const value_type &x);
void remove(const T &v);
// Possible bug: jint != size_type
jint size() const;
void sort();
%javamethodmodifiers "private";
// Only for helping implement listIterator
iterator begin();
iterator insert(iterator pos, const value_type &v);
%extend {
static void set(iterator pos, const value_type& v) {
*pos = v;
}
jint previous_index(const iterator& pos) const {
return pos == self->begin() ? -1 : std::distance(self->begin(), static_cast<std::list<T>::const_iterator>(pos));
}
jint next_index(const iterator& pos) const {
return pos == self->end() ? self->size() : std::distance(self->begin(), static_cast<std::list<T>::const_iterator>(pos));
}
static iterator next(iterator pos) {
return ++pos;
}
static iterator previous(iterator pos) {
return --pos;
}
static value_type deref(const iterator& pos) {
return *pos;
}
static void advance(iterator& pos, jint index) {
std::advance(pos, index);
}
bool has_next(const iterator& pos) const {
return pos != $self->end();
}
}
%javamethodmodifiers "public";
};
}
%typemap(javaimports) std::list %{
import java.util.AbstractSequentialList;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Collection;
%}
%typemap(javabase) std::list "AbstractSequentialList<$typemap(autobox,$1_basetype::value_type)>"
#define JAVA_VALUE_TYPE $typemap(autobox,$1_basetype::value_type)
#define JAVA_ITERATOR_TYPE $typemap(jstype, $1_basetype::iterator)
%typemap(javacode,noblock=1) std::list {
public $javaclassname(Collection c) {
this();
ListIterator<JAVA_VALUE_TYPE> it = listIterator(0);
for (Object o: c) {
it.add((JAVA_VALUE_TYPE)o);
}
}
public ListIterator<JAVA_VALUE_TYPE> listIterator(int index) {
return new ListIterator<JAVA_VALUE_TYPE>() {
private JAVA_ITERATOR_TYPE pos;
private JAVA_ITERATOR_TYPE last;
private ListIterator<JAVA_VALUE_TYPE> init(int index) {
pos = $javaclassname.this.begin();
$javaclassname.advance(pos, index);
return this;
}
public void add(JAVA_VALUE_TYPE v) {
// Technically we can invalidate last here, but this makes more sense
last=$javaclassname.this.insert(pos, v);
}
public void set(JAVA_VALUE_TYPE v) {
if (null==last) {
throw new IllegalStateException();
}
$javaclassname.set(last, v);
}
public void remove() {
if (null==last) {
throw new IllegalStateException();
}
$javaclassname.this.remove(last);
last=null;
}
public int previousIndex() {
return $javaclassname.this.previous_index(pos);
}
public int nextIndex() {
return $javaclassname.this.next_index(pos);
}
public JAVA_VALUE_TYPE previous() {
if (previousIndex() < 0) {
throw new NoSuchElementException();
}
last = pos;
pos = $javaclassname.previous(pos);
return $javaclassname.deref(last);
}
public JAVA_VALUE_TYPE next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
last = pos;
pos = $javaclassname.next(pos);
return $javaclassname.deref(last);
}
public boolean hasPrevious() {
return previousIndex() != -1;
}
public boolean hasNext() {
return $javaclassname.this.has_next(pos);
}
}.init(index);
}
}
このファイルには、ほとんどがちょうどListIterator
を実装するまで沸騰する、AbstractSequentialList
を実装しています。 Javaがイテレータのコンセプトを実装する方法は、C++の抽象化とは少し異なりますが、完全に異なるわけではありません。 ListIterator
の
当社のJava実装では、ほとんどが不透明なC++イテレータと、実際に必要な要件を満たすためにstd::advance
、std::distance
とoperator++
/operator--
を使用して少し余分なC++コードに呼び出すためにいくつかの接着剤の周りだけのラッパーです。接着剤の中には、Javaプログラマが期待しているように、インターフェースを安全/頑強にするために必要なさまざまなチェックがあります。 ::リストをはstdする
SWIGインタフェースは、次の主要部分で構成されていますstd::list
自体の関連部分の
- 宣言。
- 私たちは、後にSWIG内
%template
を使用するときに我々が必要とするテンプレートC++のイテレータのコードの一部をインスタンス化させるためにいくつかの余分なプライベートコード(それは実装の詳細以外としてのJavaにも意味がありませんので、一部はプライベートです)。 - それが簡単にJavaがいずれかを含め、当社のコンテナが保持していると考えていることと「タイプ「JavaはC++のようにイテレータへの不透明なハンドルを知っているタイプ」を書くために作るために
std::list
- いくつかのヘルパーマクロの輸入/基底クラスを設定します彼らがたくさん書かれているので、必要に応じてオートボクシング。
我々はラップごと
std::list<X>
のためのいくつかの追加のJavaコード:- 別のコンストラクタ別のコレクションからコピーするためのJavaコレクションインタフェースによって推奨されているように。 (これは私たちが作成したJavaイテレータを使用して、効率的に処理します)。
- 可変
ListIterator
ための要件のすべてを満たすために、一緒にすべてを接着する匿名型を返すlistIterator
抽象メソッドの実装。NOBLOCKは、プリプロセッサマクロが起こるように、オンと
これは
{ }
内にラップされていますが、その{ }
が生成されたJavaに挿入されません。このJava trick to pass data to an anonymous class during constructionも使用しましたが(代わりにthe double brace magicを使用している可能性があります)。
%module test %include "std_list.i" %include <std_string.i> %template(DoubleList) std::list<double>; %template(StringList) std::list<std::string>;
そして、それを行使するためにいくつかの実際のJava:我々はSWIGモジュール、test.iを書い実行することによって、それを検証することができる場所で
ことで
import java.util.ArrayList;
public class run {
public static void dump(java.util.AbstractCollection c) {
for (Object o: c) {
System.out.println(o);
}
}
public static void main(String[] argv) {
System.loadLibrary("test");
for (int i = 0; i < 1; ++i) {
go();
// System.gc();
}
}
public static void go() {
StringList sl = new StringList();
dump(sl);
sl.add(0,"HELLO"); // 1 arg form also worked
sl.add(1,"WORLD");
sl.add(2,"testing");
sl.add(3,"some more");
System.out.println(sl.size());
dump(sl);
sl = new StringList(new ArrayList<String>() {{
add("A");
add("B");
add("C");
}});
dump(sl);
}
}
作品期待どおり:
swig3.0 -java -c++ -Wall test.i
javac *.java
g++ -Wall -Wextra -shared -o libtest.so test_wrap.cxx -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux -fPIC -D_GLIBCXX_DEBUG
LD_LIBRARY_PATH=. java run
ギブス:
4
HELLO
WORLD
testing
some more
A
B
C
ランダムノート:hasNext()
と前方反復は、おそらくhasPrevious()
、それはそのような場合、INT std::distance
呼び出しを避けるために簡単だという理由だけで逆反復よりも高速です。
(注意:ListIteratorメンバ関数のセマンティクスが急いでいるはずのJavaドキュメントを読んでいますが、そのうちの1つ以上が間違っている可能性があります)。
- 1. SWIG C++ to Python:Pythonの引数としてstd :: listを返す
- 2. SWIGのtypemapをCのchar *からpythonの文字列
- 3. swigのtypemapを使用してC++メソッドからタプルのリストにベクトル<pair <int,int>>を返します。
- 4. SWIGのC++とJava GUIリンケージ
- 5. 使用SWIGのpython numpyの配列とC++ <vector>
- 6. SWIG C++ to Python:Pythonリストのサブクラスを生成します。
- 7. swig typemapをC++構造体からPyLongに
- 8. SWIGはどのようにして<string、string>マップをPythonでラップしますか?
- 9. 戻りベクトル<T> swig
- 10. Python swig - ctypesポインタからswig wrappedインスタンスを作成します。
- 11. SWIGとC++のコンストラクタ
- 12. Eigen3 :: Vector3dおよびstd :: vectorを持つSWIG <Vector3d>
- 13. PythonへのC++(ポインタ)のswigラッパーの作成
- 14. は、どのように私はSWIG
- 15. SWIGでpython2とpython3のモジュールを作成
- 16. リスト<T>はどのように辞書<K, List<T>で動作しますか?
- 17. SWIG C関数ポインタとJAVA
- 18. SWIG C++ Java DLL Windows
- 19. SWIGは以下のSWIGインタフェースファイルを考えると、Javaラッパープライベートメソッド
- 20. SWIG typemapからのメモリ割り当て解除
- 21. PythonでのSWIG C++のベクトルアクセス
- 22. swig char ** charへのポインタとして*
- 23. C + Python(SWIG)のプロファイリング
- 24. このswigコードはどのようにヒスイのように見えますか?
- 25. Swig(Tcl):C++プログラムの実行中にSwig関数を呼び出せますか?
- 26. SWIGとPython:手動で作成したクラスをSWIGで生成されたモジュールに追加するにはどうすればよいですか?
- 27. ディレクタを使用したC++とJava間のSWIG多型のメモリリーク
- 28. SWIGとのクロスプラットフォームインターフェイスの生成方法は?
- 29. SwigによるJavaバインディングのMakefileは失敗します
- 30. C#genericリストへの参照(JavaのList <?extendオブジェクト>と同じ)
答え:おそらく 'List'にマップしたくないのですが、 'AbstractList'を実装する方がはるかに良いアイデアです。私は前に、同様の主題に関するいくつかの答えを書いた:http://stackoverflow.com/a/12551108/168175 http://stackoverflow.com/a/8190135/168175 –
Flexo
(['AbstractSequentialList' ](https://docs.oracle.com/javase/7/docs/api/java/util/AbstractSequentialList.html)は、 'std :: list'のより良い基本クラスです)。あなたがしたい場合は、ここで等価な答えを書くことを幸せ。 – Flexo
@Flexo私のベースC++オブジェクトは 'std :: list'を使用しています。私はあなたの以前の答えが私を助けてくれると混乱していますか?もしあなたがそれを書くなら、大いに感謝します! –