Доступ к указателям DLL через Java

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
311
1

Ответы 1

Глядя на определение типа функции, я бы сделал обоснованное предположение и сказал, что 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
        );
    }
}

Другие вопросы по теме