简体   繁体   中英

Invalid memory access error from JNA and DLL

I am having trouble with JNA and a DLL file created from LabVIEW. I am able to call it when I don't use this line, the first one:

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

After this the DLL class is followed as:

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

It looks that it's trying to access some random FirstPath or I don't know what. It gives me this error.

   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)

I mean how in the world can I access the same file I am trying to write to and then call it again in the dll method? I tried and nothing worked. Can someone help me? I would appreciate this very much!

Note: This is my DllClass:

  public interface DLLClass extends Library{

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

extends Libray comes from jna.jar.

This is what inside my FileDll.h file:

#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)

Your stack trace gives a strong hint at the source of the problem.

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

If you look at the JNA source for invokeString() you'll see it's calling the getString() method, assuming 1-byte character encoding (ASCII). But Windows by default uses a 2-byte Unicode character encoding, and this method needs to know to use a wide string so it will call getWideString() .

This can be addressed by assigning the appropriate Type Mapper when loading the DLL. The easiest way to do this is to add the default Windows type mapping:

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

That is the standard way of doing it with a WinAPI method. Technically if your method is not part of the WinAPI you should probably define your own type mapper, using that one as a template.

After you have tried Daniel's suggestion, and in case it does not work, please try this:

Replace this line:

public interface DLLClass extends Library

With this line:

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

Another potential problem that I can think of is that you might be using a somewhat recent version of java, but your version of JNA is old, or your version of library "DLLFile" is old, and it does not know that the internal representation of java strings has changed in recent java versions, storing the bytes in whatever encoding was used at the time of creation instead of always UTF16. But this is really grasping at straws here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM