Используйте C ++ DLL из Java с JNA - PullRequest
1 голос
/ 31 января 2020

Я пытаюсь использовать DLL из C ++ с JNA для связи с элементом управления Fanu c цифри c, из Java программы, но всегда получаю эту ошибку: Исключение в потоке "main" java .lang .Error: Недопустимый доступ к памяти

Специфический метод c 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);

И в объявлении в Java Я использую это:

short cnc_allclibhndl3(String ipaddr, short port, NativeLong timeout, short FlibHndl);

Я пробовал с разными типами сопоставлений, но всегда получаю одну и ту же ошибку.

Можете ли вы сказать мне, правильно ли это объявление?

Это моя последняя программа:

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

РЕДАКТИРОВАТЬ ПОСЛЕ ОТВЕТА Даниэля Виддиса.

Здравствуйте, я попробовал ваше решение и впервые работаю. Приложение отвечает «ret = -16», что означает «EW_SOCKET (-16) Ошибка сокета». Это нормально, потому что на другой стороне нет CN C. Проблема возникает, когда я соединяю реальный CN C с реальным IP, затем появляется та же ошибка, что и в первый раз.

Это мой действительный код:

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)

1 Ответ

1 голос
/ 01 февраля 2020

Последний аргумент в функции cnc_allclibhndl3() является указателем на short:

unsigned short *FlibHndl

Таким образом, правильное отображение этого должно быть ShortByReference. Это инициализирует указатель на short в другом месте в памяти. В настоящее время вы передаете нулевой (0) указатель и запрашиваете нативный метод для доступа к этой памяти!

Кроме того, вам нужна переменная C long, сопоставленная с NativeLong в Java, а не long. Длина Java всегда 64-битная, но C long зависит от ОС и битности. В Windows это на самом деле всегда 32-битный, так что если ваш код Windows - только вы можете даже использовать int, но в целом / кроссплатформенный вы должны использовать NativeLong для этого отображения.

Кроме того, существует соглашение о том, чтобы вызов Native.load() находился в интерфейсе как переменная stati c INSTANCE, а не определял его как встроенный, как вы сделали.

Попробуйте это:

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