结合使用Java和JNA中的C ++ DLL [英] Use C++ DLL from Java with JNA

查看:81
本文介绍了结合使用Java和JNA中的C ++ DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试通过JNA使用C ++中的DLL与Java程序的Fanuc数字控件进行通信,但始终会收到以下错误消息: 线程主"中的异常java.lang.Error:无效的内存访问

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 ++方法是此 https://www.inventcom.net/fanuc-focas-library/handle/cnc_allclibhndl3

The specific C++ method that I tried to use is this 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);

在Java的声明中,我使用以下代码:

And in the declaration in Java I use this:

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);
    }
}

在Daniel Widdis响应后进行编辑.

EDIT AFTER Daniel Widdis RESPONSE.

您好,我尝试了您的解决方案,这是我第一次工作.应用程序以"ret = -16"响应,这意味着"EW_SOCKET(-16)套接字错误".这是正常的,因为另一侧没有任何CNC. 当我用真实IP连接真实CNC时出现问题,然后出现与第一次相同的错误.

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". It is normal, for not having any CNC on the other side. The problem appears when I connect a real CNC with real IP, then appears the same error that the first time.

这是我的实际代码:

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());
    }
}

这是错误:

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)

推荐答案

cnc_allclibhndl3()函数中的最后一个参数是指向short的指针:

The last argument in the cnc_allclibhndl3() function is a pointer to a short:

unsigned short *FlibHndl

因此,正确的映射应该是

So the proper mapping of that should be a ShortByReference. That will initialize a pointer to a short elsewhere in memory. Currently you're passing a null (0) pointer and asking the native method to access that memory!

此外,您需要在Java中将C long变量映射到NativeLong,而不是long. Java long始终为64位,但是C long随操作系统和位的不同而不同.在Windows中,实际上始终是32位,因此,如果您的代码仅用于Windows,则甚至可以使用int,但是在一般/跨平台中,应使用NativeLong进行该映射.

Also, you need the C long variable mapped to NativeLong in Java rather than long. Java long is always 64 bit, but C long varies based on OS and bitness. 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.

此外,惯例是Native.load()调用必须在接口中作为静态INSTANCE变量,而不是像您已经完成的那样直接内联定义.

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.

尝试一下:

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());
    }
}

这篇关于结合使用Java和JNA中的C ++ DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆