简体   繁体   中英

JNA, Mapping and pointers references

I need to use DLL inside my Java application. DLL is exporting some set of functions, authors called it "Direct DLL API". I'm trying to define in java equivalent of following function declaration:

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

Inside my interface that extends Library I declared it as follows:

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

Problem is everytime I get an error:

Exception in thread "main" java.lang.Error: Invalid memory access

So basically I'm stuck at this point.

HXCEEDCMP hComp - is suppose to store handler to the function, and works fine as WString for init DLL / destroying DLL functions so I kept it like this.

The header reference "creature" is:

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

const BYTE* pcSource - is the source data for compression, inside my code I instantiate it this way:

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

  return pointer;
}

DWORD dwSourceSize - for this im getting reserved Memory size in this way:

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

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

BYTE** ppcCompressed - function should populate ppcCompressed reference after work is done. I assume I made a mistake there, by doing it in this way:

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

DWORD* pdwCompressedSize - returned by function size of compressed data. I map it in this way:

IntByReference intByReference = new IntByReference();

Not sure if it is good idea aswell..

BOOL bEndOfData - i need to set it to true.

So finally my method call, which returns an error looks like this:

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

Any help will be appreciated. Thank you.

I think i solved the issue (thanks for comments guys). Maybe for someone using this library it will be useful:

In the end the main problem was with handler declaration and the ppcCompressed value.

I used the following solution which works fine for me:

Method declarations inside java interface:

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);

Usage:

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());
}

Example output:

Compression result: 0 Data: KLJNLJNII yK

Decompression result: 0 Data: abcabcddd

Free memory and shutdown

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM