通过Java访问DLL指针

时间:2019-02-08 01:53:03

标签: java c++ dll jna

我正在使用Java(JNA)访问DLL代码。这是我正在使用的DLL:

U32 ReadMemU32(U32 Addr, U32 NumItems, U32* pData, U8* pStatus);

这是我的示例代码:

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.*;
import com.sun.jna.*;
import java.lang.*;
import java.util.*;

import com.sun.jna.*;
import java.lang.*;

public class DLL1 {

    @UserFunction(Description="DLL1 Java wrapper", Name = "DLL1")
    public static String DLL1(
        @UserFunction.Arg(Name = "Address", Description = "Register Address")
        String Address
    ) throws Exception {

        byte Status[] = new byte[1];
        PointerByReference Data = new PointerByReference ();

        long Addr = Long.parseLong(Address.substring(2, Address.length()));
        DllInterface.INSTANCE.ReadMemU32(Addr, 1, Data, Status);
        System.out.println("Data = " + Data);
        System.out.println("Data.getValue() = " + Data.getValue()); 

        return null;
    }

    // C++ function definition and tell which DLL to fetch
    public interface DllInterface extends Library {

        DllInterface INSTANCE = (DllInterface) Native.loadLibrary("<dll name>", DllInterface.class);

        long ReadMemU32(long Addr, long NumItems, PointerByReference pData, byte[] pStatus);
    }
}

我得到的结果是:

Data = allocated@0xe25ac90 (8 bytes)(com.sun.jna.ptr.PointerByReference@e25ac90)
Data.getValue() = native@0xaaaaaaaa

结果(0xaaaaaaaa)与我期望的不匹配。

我是Java的新手,我不确定PointerByReference是否适用于U32* pData。请指教。

1 个答案:

答案 0 :(得分:2)

看看函数的类型定义,我会做出有根据的猜测,并说pData是函数将读取存储器写入的数组指针。您可以在此处直接使用int[]。由于状态是通过指针作为out参数返回的,因此可以使用ByteByReference

在Java中,long表示64位整数,等效于C ++的long long。由于类型为U32,因此可以安全地猜测它所引用的是32位整数。这将是int。您可以检查JNA的类型映射here

还请注意,由于该函数接受地址的32位整数,因此无法将64位地址传递给该函数。

我猜想此功能的一个正确映射是:

int ReadMemU32(
    int address,
    int numItems,
    int[] pData,
    ByteByReference status
);

如果您的函数确实只需要从内存中读取一个32位整数,则可以将pData的类型更改为IntByReference并以与status相同的方式使用它参数的ByteByReference

由于该函数返回一个整数,所以我猜想它会返回读取的字节数。如果是这样,检查此值是否与期望的值匹配很重要。检查库的文档中有关返回值和错误状态的内容。

尝试一下:

import java.lang.*;
import java.util.*;

import com.sun.jna.*;
import com.sun.jna.ptr.*;

public class DLL1 {

    @UserFunction(Description="DLL1 Java wrapper", Name = "DLL1")
    public static String DLL1(
        @UserFunction.Arg(Name = "Address", Description = "Register Address")
        String Address
    ) throws Exception {

        String addressWithoutPrefix = Address.substring(2)
        int parsedAddress = Integer.parseInt(addressWithoutPrefix, 16)

        int bytesToRead = 1;
        int[] buffer = new int[bytesToRead];

        ByteByReference status = new ByteByReference(0);

        int BytesRead = DllInterface.INSTANCE.ReadMemU32(
            parsedAddress,
            bytesToRead,
            buffer,
            status
        );

        System.out.println("Status = " + status.getValue());
        System.out.println("Bytes read = " + bytesRead);
        System.out.println("Data = " + Arrays.toString(buffer));

        return null;
    }

    // C++ function definition and tell which DLL to fetch
    public interface DllInterface extends Library {

        DllInterface INSTANCE = (DllInterface) Native.loadLibrary("<dll name>", DllInterface.class);

        int ReadMemU32(
            int address,
            int numItems,
            int[] pData,
            ByteByReference status
        );
    }
}