DLL issues and Invalid Memory Access

老子叫甜甜 提交于 2020-01-14 10:34:10

问题


So here is my situation. I am tasked with porting over part of a program from pascal written in a delphi IDE, at least I believe, to a Java program. I was not present at the creation of the program being ported over so I have almost no knowledge of the inner workings other than watching what it does as a final product. None-the-less, I have started transferring it over and hit a roadblock with their .dll calls.

Their .dll calls are represented here:

unit impdll;

interface

uses
    Classes, Sysutils;
type
    TChar80 = array[0..80] of char;

procedure GetElev (var a,b:double; var Elevate,ErrCode:LongInt); stdcall;
procedure ClxGen (var errCode:LongInt); stdcall;
procedure RunGen (var ErrCode:Integer;var XFileName:Tchar80;XLen: integer); stdcall;

implementation

procedure GetElev (var a,b:double; var Elevate,ErrCode:LongInt); stdcall; external 'Getelev.dll' name 'GETELEV';
procedure ClxGen (var errCode:LongInt); stdcall; external 'ClxGen.dll' name 'CLXGEN';
procedure RunGen (var ErrCode:Integer;var XFileName:Tchar80;XLen: integer); stdcall; external 'Rungen.dll' name '_rungen@12';

end.

I have no real knowledge of what their .dlls do or even take in or out as parameters or in what code they are written. Although, the nature of their names and the knowing what this portion of the program does, I can guess that the first of the three .dll files get elevation based on a lat long position, a and b, and return it to the doubles and the elevation to the longint. After using "dumpbin.exe /EXPORTS" on the getelev.dll file it gave me this as the only function name, which makes sense based on their code and call of the .dll:

ordinal   hint   RVA     name
      1      0   0000100 GETELEV

Through research I found out that having an '@#' after the name means a certain amount of bytes are passed as parameters, so I am assuming this means they get no parameters. Is my reasoning wrong here?

Also, is there a way to determine the return type here? I would assume that CLXGEN has no return type simply because a procedure was being used instead of a function, or are procedures generally used over functions in interfaces?

Anyways, by using JNA, I was able to partially get the .dll libraries into Java. I ended up with my code that looks like this:

public class MainProgram {

public interface LibraryCalls extends Library {
    LibraryCalls INSTANCE = (LibraryCalls) Native.loadLibrary("getelev",LibraryCalls.class);        
    public void GETELEV(double a, double b, int Elevate, int ErrCode);

}

public static void main(String[] args) 
{
    System.loadLibrary("getelev");
    LibraryCalls newCall = LibraryCalls.INSTANCE;
    newCall.GETELEV(24.726348,-81.051194,0,0);

}

}

This is where my trouble begins. I get an Invalid Memory Access seen below:

Exception in thread "main" java.lang.Error: Invalid memory access
    at com.sun.jna.Native.invokeVoid(Native Method)
    at com.sun.jna.Function.invoke(Function.java:408)
    at com.sun.jna.Function.invoke(Function.java:354)
    at com.sun.jna.Library$Handler.invoke(Library.java:244)
    at com.sun.proxy.$Proxy0.GETELEV(Unknown Source)
    at markSimTest.MainProgram.main(MainProgram.java:22)

After researching about this Invalid memory access I found many people talking about mappings and whether or not they were correct could affect this, so I am wondering if that might be my problem? If not this then maybe JNA does not work for the type of .dll this is simply because it was written in an unknown language, which if this is the case I would guess it is a pascal .dll, if that is even possible. As you can tell I do not have a lot of knowledge in .dlls

Also on the same topic, I had trouble finding out how the .dll will return lat or long or elevation if it is a void function and takes no parameters. Does the procedure do something special to get these numbers from the .dll?

Any help at all, even partial, would be greatly appreciated.

Solution Edit:

A rather simple solution now that I look at it, but at the time I could not see such a solution simply because I did not have enough knowledge on this subject.

Here is the updated Java code that worked:

public interface LibraryCalls extends StdCallLibrary{
    LibraryCalls INSTANCE = (LibraryCalls) Native.loadLibrary("getelev",LibraryCalls.class);

    public void GETELEV(Pointer a, Pointer b, Pointer Elevate, Pointer ErrCode);
}


public static void main(String[] args) 
{
    Pointer lat = new Memory(Native.getNativeSize(Double.TYPE));
    lat.setDouble(0, 34.769823);
    Pointer lon = new Memory(Native.getNativeSize(Double.TYPE));
    lon.setDouble(0, -87.654147);
    Pointer elevate = new Memory(Native.getNativeSize(Integer.TYPE));
    elevate.setInt(0, 0);
    Pointer errCode = new Memory(Native.getNativeSize(Integer.TYPE));
    errCode.setInt(0, 0);

    LibraryCalls newCall = LibraryCalls.INSTANCE;
    newCall.GETELEV(lat,lon,elevate,ErrCode);
}

来源:https://stackoverflow.com/questions/44078826/dll-issues-and-invalid-memory-access

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!