私は JNA を使用して、Java から私が作成した小さな C ライブラリへのネイティブ関数呼び出しを比較的成功させてきました。構造体のマッピング、メモリ管理、および参照渡しのトリックを理解すれば、構造体またはポインターを一方から他方に渡すことがうまく機能します。
私は今、Java から C に構造体の配列を渡そうとしています。構造体の C コードは次のとおりです。
typedef struct key {
int length;
void *data;
} key_t;
私はJavaで一致する定義を持っています:
public class Key extends Structure {
public int length;
public Pointer data;
public Key() {
this.setFieldOrder(new String[] {"length", "data"});
}
public void setAsLong(long value) {
this.length = 8;
this.data = new Memory(this.length);
this.data.setLong(0, value);
}
public long longValue() {
return this.data != null ? this.data.getLong(0) : Long.MIN_VALUE;
}
};
ドキュメントとオンラインで読んだ内容を理解していれば、Java 側で次の手順を実行して、配列を連続したメモリ セクションとして作成する必要があります。
Key[] keys = new Key().toArray(2);
for (int i=0; i<2; i++) {
k.setAsLong(42+i);
}
ここまでは順調ですね。Key
を使用してJavaの各構造のコンテンツをダンプするとStructure.toString()
、期待どおりにすべてがここにあります。Key
Java から C に1 つの構造体を渡すと、long 値として設定したり、キーのコンテンツにメモリを割り当てたりするコードが正常に機能することに注意してください。配列の要素:
instance.foo(keys[0].getPointer(), keys.length);
私のC関数はもちろん次のように定義されています:
void foo(key_t *keys, size_t count) {
...;
}
配列は正しくそこに到達しkeys
ます。C 側のポインターkeys[0].getPointer()
は Java と同じアドレスを持ちますが、残念ながら配列内の各構造体のメンバーは、0/NULL
GDB で指摘されているように、次のようになります。
(gdb) print keys
$1 = (key_t *) 0x7fd7e82389e0
(gdb) print keys[0]
$2 = {length = 0, data = 0x0}
この時点で、私は正直なところ、何が起こっているのかわかりません。先ほど言ったように、構造体を 1 つだけ渡せば問題なく動作しますが、ここでは無理です。私が見ることができる唯一の違いは、Pointer
代わりに使用するJavaネイティブメソッドシグネチャですKey[]
が、配列を使用すると、次のようになります。
IllegalArgumentException: [Lfoo.bar.Key; is not a supported argument type (in method foo ...
ありがとう