Java和JNA为C函数传递参数
我正在使用JNA从C DLL调用函数: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
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方法的文档