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 会导致核心转储。

我尝试更改 ItemList 定义(在 Java 中)以使用 Item.ByValue 数组:

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 实现。然后我更改了 Java 代码以将 CLibrary.ItemList.ByReference 传递给 addItemList - 但结果相同。

我错过了什么?使用 JNA 将包含结构数组的结构从 Java 传递到 C 的适当方法是什么?

4

2 回答 2

2

正如我在上面看到的那样,您遇到了问题。

在您的代码之上,您Item.ByValueItem *上使用

但它应该是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 回答