Java和JNA为C函数传递参数

Java和JNA为C函数传递参数,java,c,pointers,jna,Java,C,Pointers,Jna,我正在使用JNA从C DLL调用函数: extern _declspec( dllexport ) int ReadCP(IN OUT unsigned char* Id, IN OUT unsigned int* Size); 在Java中,我将JNA接口用于以下方法: int ReadCP(byte[] id, IntByReference size); 我成功加载了DLL并以这种方式调用了该方法: byte[] id= new byte[10]; IntByReference size

我正在使用JNA从C DLL调用函数:

extern _declspec( dllexport )
int ReadCP(IN OUT unsigned char* Id, IN OUT unsigned int* Size);
在Java中,我将JNA接口用于以下方法:

int ReadCP(byte[] id, IntByReference size);
我成功加载了DLL并以这种方式调用了该方法:

byte[] id= new byte[10];
IntByReference size = new IntByReference();
IMimicDLL demo = (IMimicDLL) Native.loadLibrary("MyLib", IMimicDLL.class);
size.setValue(10);
//....
while(true){
  demo.ReadCP(id, size);
  //...
}

循环
id
中的第一次有一个正确的值,但它保持相同的值,即使逻辑应该更改它。有什么问题吗?这与指针有关吗?

您对
id
的映射是错误的:您不能通过JNA将基元数组作为参数传递

您应该更改界面以使用
指针

int ReadCP(Pointer id, IntByReference size);
然后为id分配本机端内存:

Pointer id = new Memory(10);
从函数中传递并检索
id
后,您将从本机内存中获取字节数组:

byte[] idByteArray = id.getByteArray(0, 10);
有一些,例如
getString()
,可能更适用于您试图获取的
Id
字段的最终类型,也可能不适用于此类型

就值更新一次(而不是在重复调用之后)而言,这听起来像是在某个时候系统正在拍摄当前硬件状态的“快照”,您必须找到刷新该快照的方法。故障排除步骤包括:

  • 清除数组/指针中的数据,并查看是否从C端DLL重新填充数据(问题不在JNA中,而是在使用DLL中)
  • 在整个过程中检查
    大小
    变量,确保其保持预期值10。当您移除卡时,可能会返回0,如果您尝试读取新值(长度为0),则不会覆盖索引0之后的旧数组
  • 选择先使用哪张卡
  • 交替启动程序、加载和交换卡的顺序,以收集数据,该过程的哪个步骤似乎会导致值粘滞
  • 在DLL中查找“刷新”或“重新加载”硬件状态快照的方法
  • 在循环之间尝试

在使用JNA时,这些步骤中的大多数都超出了您的问题范围,需要您提供更多关于正在使用的DLL的信息,以便我们进一步提供帮助。

您的
id
映射错误:您无法通过JNA将基元数组作为参数传递

您应该更改界面以使用
指针

int ReadCP(Pointer id, IntByReference size);
然后为id分配本机端内存:

Pointer id = new Memory(10);
从函数中传递并检索
id
后,您将从本机内存中获取字节数组:

byte[] idByteArray = id.getByteArray(0, 10);
有一些,例如
getString()
,可能更适用于您试图获取的
Id
字段的最终类型,也可能不适用于此类型

就值更新一次(而不是在重复调用之后)而言,这听起来像是在某个时候系统正在拍摄当前硬件状态的“快照”,您必须找到刷新该快照的方法。故障排除步骤包括:

  • 清除数组/指针中的数据,并查看是否从C端DLL重新填充数据(问题不在JNA中,而是在使用DLL中)
  • 在整个过程中检查
    大小
    变量,确保其保持预期值10。当您移除卡时,可能会返回0,如果您尝试读取新值(长度为0),则不会覆盖索引0之后的旧数组
  • 选择先使用哪张卡
  • 交替启动程序、加载和交换卡的顺序,以收集数据,该过程的哪个步骤似乎会导致值粘滞
  • 在DLL中查找“刷新”或“重新加载”硬件状态快照的方法
  • 在循环之间尝试

关于使用JNA,这些步骤中的大多数都超出了您的问题范围,需要您提供更多关于正在使用的DLL的信息,以便我们进一步提供帮助。

这里是while循环中的业务登录

while(true){ 
 try { 
   Thread.sleep(1500); 
 } catch (InterruptedException e1) 
 { 
   e1.printStackTrace();
 } 
if(demo.cardPresent() == 0 && read == false){
 demo.ReadCP(id, size);
 try { 
System.out.println(" -- id : " + new String(id.getByteArray(0, 10),"UTF-8"));
 read = true;
 continue; 
} catch (Exception ex) {
 ex.printStackTrace();
 }
}else if(demo.cardPresent() != 0){
read = false;
} 

这里是while循环中的业务登录

while(true){ 
 try { 
   Thread.sleep(1500); 
 } catch (InterruptedException e1) 
 { 
   e1.printStackTrace();
 } 
if(demo.cardPresent() == 0 && read == false){
 demo.ReadCP(id, size);
 try { 
System.out.println(" -- id : " + new String(id.getByteArray(0, 10),"UTF-8"));
 read = true;
 continue; 
} catch (Exception ex) {
 ex.printStackTrace();
 }
}else if(demo.cardPresent() != 0){
read = false;
} 

谢谢你的回答,但我仍然有相同的问题:在while循环中,我有一个逻辑,应该读取卡id,我得到了相同的第一张卡的id,即使我更改了卡,id也不会更改。这就是我所能帮助的全部,使用你提供的Java/JNA片段。有更多的文档可用于DLL方法吗?以下是我在while循环中的逻辑
while(true){try{Thread.sleep(1500);}catch(InterruptedException e1){e1.printStackTrace();}if(demo.cardPresent()=0&&read==false){demo.ReadCP(id,size);try{System.out.println(--id:“--id:”+新字符串(id.getByteArray(0,10),“UTF-8”);read=true;continue;}catch(异常值ex){ex.printStackTrace();}}}否则如果(demo.cardPresent()!=0){read=false;}
不能通过JNA将数组作为参数传递,这只是我很久以前放弃JNA并刚刚学会如何可靠地执行JNI的原因之一。一旦您知道了如何实现Java
静态本机字节[]getByteArray()的JNI端
静态本机int fillInByteArray(字节arr[])方法几乎微不足道。公平点,@AndrewHenle。如果您有能力编写自己的C语言,出于各种原因,这是首选。然而,如果您被其他人的DLL卡住了,无法编写自己的DLL,那么JNA是一个不错的备份。(注意:我编辑我的帖子是为了澄清“原始数组”。你可以传递结构数组、指针数组或JNA保留本机内存的其他东西。)谢谢你的回答,但我仍然有一个相同的问题:在while循环中,我有一个应该读取卡id的逻辑,即使我换了卡,我也得到了相同的第一张卡的id,id没有改变。这就是我所能帮助的全部,使用您提供的Java/JNA片段。是否有更多关于DLL方法的文档