Недопустимая ошибка доступа к памяти из JNA и DLL - PullRequest
1 голос
/ 06 ноября 2019

У меня проблемы с JNA и файлом DLL, созданным из LabVIEW. Я могу вызвать его, когда я не использую эту строку, первая:

    FileWriter writer = new FileWriter(FirstPath);
    BufferedWriter writing = new BufferedWriter(writer);
    writing.write("Here goes my strings");
    writing.close();

После этого класс DLL выглядит следующим образом:

   DLLClass dll = (DLLClass)Native.loadLibrary("DLLFile",DLLClass.class);
   dll.myMethodInsideDLLClass(FirstPath,SecondPath,ThirdPath);

Похоже, что этопытаясь получить доступ к какой-то случайной FirstPath или я не знаю что. Это дает мне эту ошибку.

   Exception in thread "AWT-EventQueue-0" java.lang.Error: Invalid memory access
   at com.sun.jna.Native.getStringBytes(Native Method)
   at com.sun.jna.Native.getString(Native.java:2224)
   at com.sun.jna.Pointer.getString(Pointer.java:681)
   at com.sun.jna.Function.invokeString(Function.java:667)
   at com.sun.jna.Function.invoke(Function.java:434)
   at com.sun.jna.Function.invoke(Function.java:361)
   at com.sun.jna.Library$Handler.invoke(Library.java:265)
   at com.sun.proxy.$Proxy0.myMethodInsideDLLClass(Unknown Source)

Я имею в виду, как в мире я могу получить доступ к тому же файлу, в который я пытаюсь записать, и затем вызвать его снова в методе dll? Я пытался и ничего не получалось. Кто-нибудь может мне помочь? Я был бы очень признателен за это!

Примечание: это мой DllClass:

  public interface DLLClass extends Library{

  public int myMethodInsideDLLClass(String 
  FirstPath, String SecondPath, String ThirdPath);
  }

расширяет Libray от jna.jar.

Вот что внутри моего файла FileDll.h:

#ifdef __cplusplus
extern "C" {
#endif


int32_t __cdecl myMethodInsideDLLClass(
    char FirstPath[], char SecondPath[], 
    char ThirdPath[]);


MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);

void __cdecl SetExcursionFreeExecutionSetting(Bool32 value);

#ifdef __cplusplus
} // extern "C"
#endif

#pragma pack(pop)

Ответы [ 2 ]

1 голос
/ 06 ноября 2019

После того, как вы попробовали предложение Даниила, и если оно не работает, попробуйте следующее:

Замените эту строку:

public interface DLLClass extends Library

На эту строку:

public interface DLLClass extends com.sun.jna.win32.StdCallLibrary

Другая потенциальная проблема, о которой я могу подумать, заключается в том, что вы можете использовать несколько более позднюю версию Java, но ваша версия JNA устарела, или ваша версия библиотеки «DLLFile» старая, и она не знает, чтовнутреннее представление строк Java изменилось в последних версиях Java, сохраняя байты в любой кодировке, использованной во время создания вместо всегда UTF16. Но это действительно цепляет за соломинку здесь.

1 голос
/ 06 ноября 2019

Ваша трассировка стека дает сильный намек на источник проблемы.

at com.sun.jna.Pointer.getString(Pointer.java:681)
at com.sun.jna.Function.invokeString(Function.java:667)

Если вы посмотрите на JNA-источник для invokeString(), вы увидите, что он вызываетgetString() метод, предполагающий 1-байтовую кодировку символов (ASCII). Но Windows по умолчанию использует 2-байтовую кодировку Unicode, и этот метод должен знать, чтобы использовать широкую строку, поэтому он вызовет getWideString().

. Эту проблему можно решить, назначив соответствующий преобразователь типов при загрузке. DLL. Самый простой способ сделать это - добавить сопоставление типов Windows по умолчанию:

DLLClass dll = (DLLClass) Native.loadLibrary("DLLFile", DLLClass.class,
    W32APIOptions.DEFAULT_OPTIONS);

Это стандартный способ сделать это с помощью метода WinAPI. Технически, если ваш метод не является частью WinAPI, вы, вероятно, должны определить свой собственный преобразователь типов, используя его в качестве шаблона.

...