2012-03-13 11 views
0

イム空です。構造体の配列を返すためにいくつかのテストをしています。まず構造体は、JNAを経由して、Javaから使用することができますC++ライブラリを構築しようとしている

C++:

namespace structures 
{ 
    typedef struct _Point { 
     int x, y; 
    } Point; 
} 

のJava:私は、次の構造体を作成しました

extern "C" __declspec(dllexport) structures::Point* getPoints(){ 
    structures::Point *p; 
    p = (structures::Point *) malloc(4 * sizeof(structures::Point)); 
    p[0].x = 10; 
    p[0].y = 20; 
    p[1].x = 30; 
    p[1].y = 40; 
    p[2].x = 50; 
    p[2].y = 60; 
    p[3].x = 70; 
    p[3].y = 80; 
    return p ; 
:だから

public class Point extends Structure { 
    public Point() { 
    // required for toArray() 
    } 

    public Point(Pointer pointer) { 
    super(pointer); 
    } 

    public int x, y; 
} 

を、私はポイントの配列を返すC++メソッドを持っています

とJavaでこれは、ライブラリへのアクセスを宣言するインタフェースです。

public interface Multiplyt extends Library{ 
    Pointer getPoints(); 
} 

そして、これは、ライブラリをテストするコードです:

Pointer pointer = test.getPoints(); 
Point point, points[]; 
point = new Point(pointer); 
points = (Point[]) point.toArray(4); 
System.out.println("0x:"+points[0].x + " 0y:" + points[0].y + " 1x:"+ points[1].x + " 1y:" + points[1].y); 
System.out.println("2x:"+points[2].x + " 2y:" + points[2].y + " 3x:"+points[3].x + " 3y:" + points[3].y); 

それらのコマンドの出力は次のとおりです。

0x:0 0y:0 1x:30 1y:40 
2x:50 2y:60 3x:70 3y:80 

あなたが見ることができるように、位置0ポイント構造が持っていますxまたはyの値はありません(0と0があり、10と20である必要があります)。なぜこうなった?どうすれば修正できますか?あなたの構造体リターンの理由で

答えて

2

構造体データは初期化されていません。これは、構造体をポインタ値から初期化した後で、Structure.read()を呼び出さないためです。

JNAは、いくつかの例では、暗黙的な同じメモリに裏打ちされた配列に単一の構造を拡大してネイティブ関数呼び出しの後/前、またはときのように、あなたのためStructure.read()を呼び出します。ただし、後者の場合、JNAはtoArray()を呼び出すときにJNAが既に初期化されていると仮定しているため、最初の要素は初期化されていません。

あなたはポインタではなく構造を返すように関数を宣言

、JNAは、それはあなたのために()Structure.readを呼び出す必要があることを推測することができます。

+0

ありがとうございます。配列への呼び出し後にポイント上の ".read()"を呼び出すと、アワビコードが動作します。私はまた、C++コードを同じままにして、構造ポイントを返すためにJavaでインターフェースを宣言しようとしましたが、point.read()を呼び出す必要もありません。 –

+1

この場合、.toArray()を呼び出す前に、構造体(Pointer)コンストラクターでStructure.read()を呼び出す必要があります。構造体が配列の最初の要素であることをJNAが認識すると、構造体の自動読み書き機能の一部としてStructure.read()/。write()が呼び出されるたびに残りの要素が読み書きされます。ですから、コンストラクタで読み込みを行うか、または冗長な読み込みを避けるためにtoArray()を呼び出す前に行うべきです。 – technomage

0

ポインタであるので、あなたは、戻り値の型は、構造体のポインタであることをJNAを伝える必要があり、あなたがStructure.ByReferenceを実装することを宣言しなければならないとStructure.ByValue

​​

その後、

public interface Multiplyt extends Library{ 
Point.ByReference getPoints(); 
} 

Point.ByReferenceはJNAを解析することができるC言語でのポイント*と同じである

Point.ByReference pointer = test.getPoints(); 
Point points[]; 
points = (Point[]) pointer.toArray(4); 
System.out.println("0x:"+points[0].x + " 0y:" + points[0].y + " 1x:"+ points[1].x + " 1y:" + points[1].y); 
System.out.println("2x:"+points[2].x + " 2y:" + points[2].y + " 3x:"+points[3].x + " 3y:" + points[3].y); 
+0

それは完璧に働いています。ありがとうございました。 mallocで割り当てられたメモリを解放したい場合は、空き(pt)メソッドを実装すれば十分でしょう.ptはjavaの "pointer"オブジェクトに対応するPoint *です。 –

+0

ByReferenceとByValueの定義/使用法は、デフォルト以外のセマンティクスを使用する場合にのみ必要です。デフォルトでは、構造体の戻り値と引数は参照として扱われ、他の構造体にネストされた構造体は値として扱われます。 – technomage

+0

ソリューションは技術的に正しいですが、あなたの説明は、それが問題を修正する理由* *を示し、同様の問題に無関係な余分な要素を導入しません。 – technomage