我正在编写一个可以访问C ++ dll usnig JNA的java应用程序。所以我准备了一个C dll来在JNA和C ++第三方dll之间进行通信。我有这两个结构:
C代码:
struct Struct1
{
uint32_t Size;
unsigned char* Data;
};
struct Struct2
{
uint32_t Struct1_Nbr;
Struct1* struct1_elements;
};
bool Open(char* fileName, Struct2** struct2);
现在我在java应用程序中编写相应的JNA代码,我想访问" unsigned char * Data"没有复制这些数据,因为它是大量的数据。 我怎样才能使用" Memory"或者指针"指针" JNA类型要执行此任务吗?
这是我的尝试:
public class Test
{
public static class Struct1 extends com.sun.jna.Structure {
public Struct1(){}
public Struct1(Pointer pointer){
super(pointer);
read();
}
public static class Struct1ByValue extends Struct1 implements com.sun.jna.Structure.ByValue{};
public int Size;
public Memory Data;
public static class Struct1ByReference extends Struct1 implements com.sun.jna.Structure.ByReference{}
@Override
protected List getFieldOrder() {
// TODO Auto-generated method stub
return Arrays.asList("Size", "Data");
};
public static class Struct2 extends com.sun.jna.Structure {
public Struct2 (){}
public Struct2 (Pointer pointer){
super(pointer);
read();
}
public int Struct2_Nbr;
public Struct1.Struct1ByReference struct1_elements = new Struct1.Struct1ByReference();
public static class Struct2ByValue extends Struct2 implements com.sun.jna.Structure.ByValue{};
public static class Struct2ByReference extends Struct2 implements com.sun.jna.Structure.ByReference{}
@Override
protected List getFieldOrder() {
// TODO Auto-generated method stub
return Arrays.asList("Struct1_Nbr", "struct1_elements"));
};
}
public interface StructureProtocol extends com.sun.jna.Library{
Boolean Open(String fileName, PointerByReference struct2);
}
public StructureProtocol lib;
public Test(){
this.lib = (StructureProtocol) Native.loadLibrary("TestAPI", StructureProtocol.class);
}
public static void main(String[] args) {
Test test = new Test();
PointerByReference pref = new PointerByReference();
test.lib.Open("filePath", pref);
Pointer ptr = pref.getValue();
Struct2 struct2= new Struct2(ptr);
Struct1[] struct1_array= (Struct1[])(struct2.struct1_elements).toArray(struct2.struct1_Nbr);
System.out.println("struct1_array[0]: Size = " + struct1_array[0].Size);
System.out.println("struct1_array[0]: Data= " + struct1_array[0].Data);
}
}
非常感谢任何建议。
答案 0 :(得分:0)
这是我的Solutiuon,第一稿:
在java中声明一个扩展Structure
的类(适用com.sun.jna.Structure)强>
(类中的所有字段必须是公共的,否则会出现错误,无法测量结构扩展类的大小)
public class Struct1 extends Structure{
public int Size;
public String Data;
}
在C Dll中声明并定义一个方法,它将一个指向结构的指针作为参数(我创建了一个结构并用测试值填充它)
void __declspec(dllexport) GetStruct(Struct1* a){
Struct1 s;
s.Size = 9;
s.Data = "Output";
*a = s;
}
我假设您已经成功将java应用程序连接到c dll,所以我跳过那部分(如果我的假设是错误的,请在评论中告诉我并编辑我的答案)
如果你将这些行添加到你的java代码中(注意cdll是我的C库的句柄)
Struct1 test = new Struct1();
cdll.GetStruct(test);
System.out.println("Struct1: " + test.Size + " " + test.Data);
您应该从C Dll中的Structure s获取数据。
答案 1 :(得分:0)
如果数据字段指向任意数据,请使用Pointer
。如果原生方分配,那么你什么都不做。如果Java端分配,请使用分配给该字段的Memory
对象。
对于struct*
和struct**
,看一些使用这些构造的本机代码以告诉它们代表什么是有用的,因为存在一些歧义(struct*
可以是指向单个结构的指针,也可以是指向它们的连续数组的指针。 struct**
可以是为struct*
的返回分配的存储空间,也可能是其他内容。