1

構造体へのポインタを取る関数を持つ C DLL で関数を呼び出そうとしています。この構造体 ( Data) は次のように定義されます。

struct BD
{
    char* Data;
    int Length;
};

struct EE
{
    char* Key;
    BD* Value;
};

struct Data
{
    char* Name;
    BD* Picture;

    // A NULL-terminated array of pointers to EE structures.
    EE** Elements;
};

Java では、次のようないくつかのクラスを定義しました。

public static class BD extends Structure implements Structure.ByReference {
    public byte[] Data;
    public int Length;
}

public static class EE extends Structure implements Structure.ByReference {
    public String Key;
    public BD Value;
}

public static class Data extends Structure {
    public String Name;
    public BD Picture;
    public PointerByReference Elements;
}

Dataしかし、オブジェクトを正しく設定する方法が正確にはわかりません。Nameフィールドとフィールドを理解できると思いますPictureが、フィールドを何に設定すればよいElementsですか? オブジェクトの Java 配列を作成できますEEが、そこから PointerByReference を取得するにはどうすればよいですか? Elementsとして宣言する必要があるかもしれませんがPointer[]、配列の各要素にgetPointer()for eachEEオブジェクトを入力するだけでよいでしょうか? しかし、それは正しくないように思えますか?

編集:私がやろうとしていることをよりよく理解するために:

Data data = new Data();
// Fill in Name and Picture fields.

EE[] elements = new Elements[10];
// Fill in the elements array.

// Now how do I set the Elements field on the data object from the elements array?
data.Elements = ???

Edit2:テクノメージの助けを借りて解決した方法は次のとおりです。

Data構造を次のように変更しました。

public static class Data extends Structure {
    public String Name;
    public BD Picture;
    public Pointer Elements;
}

そして、私のBD構造は次のようになります。

public static class BD extends Structure implements Structure.ByReference {
    public Pointer Data;
    public int Length;
}

Javabyte[]を JNAPointerに変換するには、以下を使用する必要がありましたByteBuffer

ByteBuffer buf = ByteBuffer.allocateDirect(bytes.length);
buf.put(bytes);
bd.Data = Natvie.getDirectBufferPointer(buf);

ByteBuffer残念ながら、JNA は構造内の s を好みません。

要素ポインターを取得するには、PointerEEオブジェクトへの s の配列を作成する必要がありました (実装については、technomage の回答を参照してくださいPointerArray)。

EE e = new EE();
// Populate e object.
// ...

// Important: ensure that the contents of the objects are written out to native memory since JNA can't do this automatically
e.write();
ptrs.add(e);

// Once each object is setup we can simply take the array of pointers and use the PointerArray
data.Elements = new PointerArray(ptrs.toArray(new Pointer[0]));

ByteBufferorを構造定義で直接使用できなかっPointerArrayたので、 に依存する必要がありましたPointer

4

1 に答える 1

2

を作成ElementsPointer、 を使用Pointer.getPointerArray(0)して対象の構造ポインタを取得します。

Structure次に、取得したそれぞれからそれぞれを初期化する必要がありますPointer( を呼び出すことを忘れないでくださいStructure.read())。

ポインターに対して自動的に間接化を実行して の配列を取得する方法はありませんが、クラスStructureのメソッドにエンコードするのは簡単です (例: )。StructureData.getElements()

編集

(読み取りではなく) 書き込み時にポインター配列を初期化するためのポインター配列実装のサンプル:

class PointerArray extends Memory {                      
        private final Pointer[] original;                                                           
        public PointerArray(Pointer[] arg) {                                                        
            super(Pointer.SIZE * (arg.length+1));                                                   
            this.original = arg;                                                                    
            for (int i=0;i < arg.length;i++) {                                                      
                setPointer(i*Pointer.SIZE, arg[i]);                                                 
            }                                                                                       
            setPointer(Pointer.SIZE*arg.length, null);                                              
        }                                                                                           
    }
}

の代わりにバニラを使用する場合、JNA はメモリを同期する必要があることを認識しないためStructure.write()、ネイティブ関数を呼び出す前に を呼び出す必要もあります( の一部としてこれを行う場合があります) 。PointerArrayPointerStructure

于 2013-07-09T21:22:05.260 に答える