Я использую 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. Пожалуйста посоветуй.




Глядя на определение типа функции, я бы сделал обоснованное предположение и сказал, что pData — это указатель массива, в который функция записывает память для чтения. Вы можете использовать int[] прямо здесь. Поскольку статус возвращается как выходной параметр через указатель, вы можете использовать ByteByReference.
В Java long относится к 64-битному целому числу, эквивалентному long long C++. Поскольку это тип U32, можно с уверенностью предположить, что он относится к 32-битному целому числу. Это будет int. Вы можете проверить сопоставления типов JNA здесь.
Обратите также внимание на то, что, поскольку функция принимает 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
);
}
}