JNA, Mapping и ссылки на указатели - PullRequest
1 голос
/ 08 марта 2019

Мне нужно использовать DLL внутри моего Java-приложения.DLL экспортирует некоторый набор функций, авторы назвали это «Direct DLL API».Я пытаюсь определить в Java эквивалент следующего объявления функции:

int XcCompress( HXCEEDCMP hComp, const BYTE* pcSource, DWORD dwSourceSize, BYTE** ppcCompressed, DWORD* pdwCompressedSize, BOOL bEndOfData );

Внутри моего интерфейса, расширяющего библиотеку, я объявил это следующим образом:

int XcCompress(WString hComp, Pointer pcSource, int dwSourceSize, Pointer[] ppcCompressed, IntByReference pdwCompressedSize, boolean bEndOfData);

Проблема возникает каждый раз, когда я получаюошибка:

Исключение в потоке "main" java.lang.Error: Неверный доступ к памяти

Так что в основном я застрял на этом этапе.

HXCEEDCMP hComp - предполагается хранить обработчик для функции и отлично работает как WString для инициализации DLL / уничтожения функций DLL, поэтому я сохранил это так.

Ссылка на заголовок "существо":

typedef HXCEEDCMP ( XCD_WINAPI *LPFNXCCREATEXCEEDCOMPRESSIONW )( const WCHAR* );

const BYTE* pcSource - это исходные данные для сжатия, внутри моего кода я создаю его следующим образом:

private static Pointer setByteArrayPointer(String dataToCompress) {
  Pointer pointer = new Memory(1024);
  pointer.write(0, dataToCompress.getBytes(), 0, 
  dataToCompress.getBytes().length);

  return pointer;
}

DWORD dwSourceSize - для этого я получаю зарезервированный объем памяти следующим образом:

String testData = "ABCDABCDABCDAAD";
Pointer source = setByteArrayPointer(testData);

(int) ((Memory)source).size()

BYTE** ppcCompressed - функция должна заполнить ссылку ppcCompressed после выполнения работы.Я предполагаю, что допустил ошибку, сделав это следующим образом:

Pointer[] compressed = {new Pointer(1024), new Pointer(1024)};

DWORD* pdwCompressedSize - возвращается по размеру функции сжатых данных.Я сопоставляю это следующим образом:

IntByReference intByReference = new IntByReference();

Не уверен, если это хорошая идея, а также ..

BOOL bEndOfData - мне нужно установить значение true.

Наконец, мой вызов метода, который возвращает ошибку, выглядит следующим образом:

xceedApiDll.XcCompress(handle, source, (int) ((Memory)source).size(), compressed, intByReference, true);

Любая помощь будет оценена.Спасибо.

1 Ответ

1 голос
/ 10 марта 2019

Я думаю, что решил проблему (спасибо за комментарии, ребята). Может быть, для кого-то, кто использует эту библиотеку, будет полезно:

В конце концов, основная проблема была с объявлением обработчика и значением ppcCompressed.

Я использовал следующее решение, которое отлично работает для меня:

Объявления методов внутри интерфейса Java:

int XcCompress(Pointer hComp, byte[] pcSource, int dwSourceSize, PointerByReference ppcCompressed, IntByReference pdwCompressedSize, int bEndOfData);
int XcUncompress(Pointer hComp, byte[] pcSource, int dwSourceSize, PointerByReference ppcUncompressed, IntByReference pdwUncompressedSize, int bEndOfdata);

Использование:

private static final XceedFunctions XCEED_DLL_API;

static {
    XCEED_DLL_API = Native.load("XceedZipX64", XceedFunctions.class);
}

private static final String TEST_DATA = "abcabcddd";

//Data pointers
private static Pointer compHandle;
private static byte[]  baSource = TEST_DATA.getBytes();
private static PointerByReference pbrCompressed = new PointerByReference();
private static PointerByReference pbrUncompressed = new PointerByReference();
private static IntByReference ibrCompressedSize = new IntByReference();
private static IntByReference ibrUncompressedSize = new IntByReference();

public static void main(String[] args) {
    try {
        boolean isSuccessfulInit = XCEED_DLL_API.XceedZipInitDLL();
        if(isSuccessfulInit) {
            compHandle = XCEED_DLL_API.XcCreateXceedCompressionW(new WString("YOUR_LICENCE_KEY_HERE"));
            int compressionResult = XCEED_DLL_API.XcCompress(compHandle, baSource, baSource.length, pbrCompressed, ibrCompressedSize, 1);
            byte[] compressed = getDataFromPbr(pbrCompressed, ibrCompressedSize);
            System.out.println("Compression result: " + compressionResult + " Data: " + new String(compressed));
            int decompressionResult = XCEED_DLL_API.XcUncompress(compHandle, compressed, compressed.length, pbrUncompressed, ibrUncompressedSize, 1);
            byte[] uncompressed = getDataFromPbr(pbrUncompressed, ibrUncompressedSize);
            System.out.println("Decompression result: " + decompressionResult + " Data: " + new String(uncompressed));
        }
    } finally {
        System.out.println("Free memory and shutdown");
        if(compHandle != null) {
            XCEED_DLL_API.XcDestroyXceedCompression(compHandle);
        }
        XCEED_DLL_API.XceedZipShutdownDLL();
    }
}

private static byte[] getDataFromPbr(PointerByReference pbr, IntByReference ibr) {
    return pbr.getValue().getByteArray(0, ibr.getValue());
}

Пример вывода:

Результат сжатия: 0 Данные: KLJNLJNII yK

Результат распаковки: 0 Данные: abcabcddd

Свободная память и выключение

...