java - JNA、映射和指针引用
问题描述
我需要在我的 Java 应用程序中使用 DLL。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);
问题是每次我得到一个错误:
线程“主”java.lang.Error 中的异常:内存访问无效
所以基本上我被困在这一点上。
HXCEEDCMP hComp
- 假设将处理程序存储到函数中,并且作为初始化 DLL / 破坏 DLL 函数的 WString 工作正常,所以我保持它这样。
标头引用“生物”是:
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
- 我需要将其设置为真。
所以最后我的方法调用,它返回一个错误是这样的:
xceedApiDll.XcCompress(handle, source, (int) ((Memory)source).size(), compressed, intByReference, true);
任何帮助将不胜感激。谢谢你。
解决方案
我想我解决了这个问题(感谢大家的评论)。也许对于使用这个库的人来说它会很有用:
最后,主要问题是处理程序声明和 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
释放内存和关机
推荐阅读
- pandas - 熊猫:重新排列多索引数据框
- ddev - 文件系统问题
- bash - 使用 ffmpeg 和 youtube-dl 从 Youtube 视频下载几秒钟的音频结果 [youtube]:没有此类文件或目录错误
- tableau-api - Tableau:显示每个工作日平均销售额的表格?
- node.js - 如果我打开开发控制台,谷歌浏览器会让我退出
- wordpress - 如何创建一个 WordPress 页面来过滤用户对问题的输入并相应地将它们引导到他们需要去的地方
- python - 将结构传递给 ctypes 中的 dll (freepie)
- python - 根据行中的第一个值向数据框添加新列
- java - 用大写字母初始化是什么意思?
- c# - 尝试导入 DTE 时在 CodeRefactoringProvider 初始化期间出现异常