0

別の構造体の配列を含む構造体を使用する C ライブラリがあります。JNAを介してJavaからこれにアクセスする正しい方法を判断するのに苦労しています。

Cコードは次のとおりです。

typedef struct Item {
    int x;
} Item;
typedef struct ItemList {
    int itemCount;
    Item* items; // an array of Item
} ItemList;

int addItemList(ItemList list)
{
    int result = 0;
    int i = 0;

    for (i=0; i<list.itemCount; i++)
    {
        result += (list.items)[i].x;
    }
    return result;
}

次の例では、C アプリケーションからこれを使用できます。

ItemList list;
list.itemCount = 3;
list.items = (Item*)malloc(sizeof(Item) * 3);
list.items[0].x = 1;
list.items[1].x = 2;
list.items[2].x = 3;
int y = addItemList(list);
printf("%d\n", y);

次のJavaコードを使用して、Javaから(JNA経由で)これにアクセスしようとしました:

public interface CLibrary extends Library {
    public static class Item extends Structure {
        public static class ByValue extends Item implements Structure.ByValue {}
        public int x;
    }
    public static class ItemList extends Structure {
        public static class ByValue extends ItemList implements Structure.ByValue {}
        public static class ByReference extends ItemList implements Structure.ByReference {}
        public int itemCount;
        public Item[] items;
    }
    int addItemList(ItemList.ByValue items);
}

...

CLibrary.Item[] items = (CLibrary.Item[])new CLibrary.Item().toArray(3);
items[0].x = 1;
items[1].x = 2;
items[2].x = 3;
CLibrary.ItemList.ByValue list = new CLibrary.ItemList.ByValue();
list.items = items;
list.itemCount = 3;
int y = clib.addItemList(list);
System.out.println(y);

ただし、上記の Java ではコア ダンプが発生します。

Item.ByValue の配列を使用するように (Java で) ItemList 定義を変更しようとしました。

public static class ItemList extends Structure {
    public static class ByValue extends ItemList implements Structure.ByValue {}
    public static class ByReference extends ItemList implements Structure.ByReference {}
    public int itemCount;
    public Item.ByValue[] items;
}

次に、使用法(Javaで)を次のように変更しました。

CLibrary.Item.ByValue[] items = (CLibrary.Item.ByValue[])new CLibrary.Item.ByValue().toArray(3);
items[0].x = 1;
items[1].x = 2;
items[2].x = 3;
CLibrary.ItemList.ByValue list = new CLibrary.ItemList.ByValue();
list.items = items;
list.itemCount = 3;
int y = clib.addItemList(list);

しかし、同じ結果になります。

私はまた、C関数の署名をに変更しようとしました

int addItemList(ItemList* list);

それに応じてCの実装を調整しました。次に、CLibrary.ItemList.ByReference を addItemList に渡すように Java コードを変更しましたが、結果は同じでした。

私は何が欠けていますか?JNAを使用してJavaからCに構造体の配列を含む構造体を渡す適切な方法は何ですか?

4

2 に答える 2

2

上で見たように、問題があります。

コードの上で、アイテムItem.ByValueで使用し ていました*

しかし、そうあるべきですItem.ByReference

于 2012-11-14T06:51:10.473 に答える
1

次の Java コードを使用して、元の C コードを操作することができました。

public interface CLibrary extends Library {
    public static class Item extends Structure {
        public static class ByReference extends Item implements Structure.ByReference {}
        public int x;
    }
    public static class ItemList extends Structure {
        public static class ByValue extends ItemList implements Structure.ByValue {}
        public int itemCount;
        public Item.ByReference items;
    }
    int addItemList(ItemList.ByValue items);
}

…

CLibrary.ItemList.ByValue list = new CLibrary.ItemList.ByValue();
list.items = new CLibrary.Item.ByReference();
list.itemCount = 3;
CLibrary.Item[] items = (CLibrary.Item[])list.items.toArray(3);
items[0].x = 1;
items[1].x = 2;
items[2].x = 3;
int y = clib.addItemList(list);
System.out.println(y);
于 2012-04-11T20:21:32.203 に答える