[英]Use C++ DLL from Java with JNA
I try to use a DLL from C++ with JNA to communicate with a Fanuc numeric control, from a Java program but always get this error: Exception in thread "main" java.lang.Error: Invalid memory access我尝试使用来自 C++ 的 DLL 和 JNA 与来自 Java 程序的 Fanuc 数字控件进行通信,但总是收到此错误:线程“main”中的异常 java.lang.Error: Invalid memory access
The specific C++ method that I tried to use is this https://www.inventcom.net/fanuc-focas-library/handle/cnc_allclibhndl3我尝试使用的特定 C++ 方法是这个https://www.inventcom.net/fanuc-focas-library/handle/cnc_allclibhndl3
FWLIBAPI short WINAPI cnc_allclibhndl3(const char *ipaddr, unsigned short port, long timeout, unsigned short *FlibHndl);
And in the declaration in Java I use this:在 Java 的声明中,我使用了这个:
short cnc_allclibhndl3(String ipaddr, short port, NativeLong timeout, short FlibHndl);
I tried with different type mappings but always get the same error.我尝试了不同的类型映射,但总是得到相同的错误。
Can you tell me if this declaration is correct?你能告诉我这个声明是否正确吗?
This is my last program:这是我的最后一个程序:
import com.sun.jna.Library;
import com.sun.jna.Native;
public class JnaFanuc {
public interface Fwlib32 extends Library {
short cnc_allclibhndl3(String ipaddr, short port, long timeout, short FlibHndl);
}
public static void main(String[] args) {
short p = 0;
int handle = 0;
short ret;
Fwlib32 fwl = (Fwlib32) Native.load("Fwlib32", Fwlib32.class);
ret = fwl.cnc_allclibhndl3("192.168.1.100", (short)8193, 10, p);
System.out.println("cnc_allclibhndl3 Ret: " + ret);
System.out.println("hndl: " + handle);
}
}
EDIT AFTER Daniel Widdis RESPONSE.在 Daniel Widdis 响应后编辑。
Hello, I tried your solution and for the first time I work.您好,我尝试了您的解决方案,这是我第一次工作。 The application responds with "ret = -16" which means "EW_SOCKET (-16) Socket error".
应用程序响应“ret = -16”,这意味着“EW_SOCKET (-16) 套接字错误”。 It is normal, for not having any CNC on the other side.
这是正常的,因为另一侧没有任何CNC。 The problem appears when I connect a real CNC with real IP, then appears the same error that the first time.
当我使用真实 IP 连接真实 CNC 时出现问题,然后出现与第一次相同的错误。
This is my actual code:这是我的实际代码:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.ShortByReference;
public class TestJNA {
public interface Fwlib32 extends Library {
Fwlib32 INSTANCE = (Fwlib32) Native.load("Fwlib32", Fwlib32.class);
short cnc_allclibhndl3(String ipaddr, short port, long timeout, ShortByReference FlibHndl);
}
public static void main(String[] args) {
ShortByReference handle = new ShortByReference((short)0);
short ret = 0;
Fwlib32 fwl = Fwlib32.INSTANCE;
ret = fwl.cnc_allclibhndl3("192.168.1.100", (short) 8193, 4, handle);
System.out.println("cnc_allclibhndl3 Ret: " + ret);
System.out.println("hndl: " + handle.getValue());
}
}
And this is the error:这是错误:
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:422)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.proxy.$Proxy0.cnc_allclibhndl3(Unknown Source)
at testjna.TestJNA.main(TestJNA.java:38)
The last argument in the cnc_allclibhndl3()
function is a pointer to a short
: cnc_allclibhndl3()
函数中的最后一个参数是一个指向short
的指针:
unsigned short *FlibHndl
So the proper mapping of that should be a ShortByReference
.所以正确的映射应该是
ShortByReference
。 That will initialize a pointer to a short
elsewhere in memory.这将初始化一个指向内存中其他地方的
short
的指针。 Currently you're passing a null (0) pointer and asking the native method to access that memory!当前,您正在传递一个空 (0) 指针并要求本机方法访问该内存!
Also, you need the C long
variable mapped to NativeLong
in Java rather than long
.此外,您需要将 C
long
变量映射到 Java 中的NativeLong
而不是long
。 Java long is always 64 bit, but C long
varies based on OS and bitness. Java long 总是 64 位,但 C
long
因操作系统和位数而异。 In Windows, that's actually always 32-bit so if your code is Windows-only you could even use int
, but in general/cross-platform you should be using NativeLong
for that mapping.在 Windows 中,这实际上总是 32 位,因此如果您的代码仅适用于 Windows,您甚至可以使用
int
,但在一般/跨平台中,您应该使用NativeLong
进行该映射。
Additionally the convention is for the Native.load()
call to be in the interface as a static INSTANCE
variable, rather than defining it inline as you've done.此外,约定是
Native.load()
调用在接口中作为静态INSTANCE
变量,而不是像您所做的那样内联定义它。
Try this:尝试这个:
public class JnaFanuc {
public interface Fwlib32 extends Library {
Fwlib32 INSTANCE = (Fwlib32) Native.load("Fwlib32", Fwlib32.class);
short cnc_allclibhndl3(String ipaddr, short port, NativeLong timeout, short FlibHndl);
}
public static void main(String[] args) {
ShortByReference handle = new ShortByReference();
short ret;
String ip = "192.168.1.100";
short port = (short) 8193;
NativeLong timeout = new NativeLong(10);
Fwlib32 fwl = Fwlib32.INSTANCE;
ret = fwl.cnc_allclibhndl3(ip, port, timeout, handle);
System.out.println("cnc_allclibhndl3 Ret: " + ret);
System.out.println("hndl: " + handle.getValue());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.