vui*_*uis 5 java pointers jna intptr
我在 C# 中有一个从 .dll 调用的方法
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int find([MarshalAs(UnmanagedType.AnsiBStr, SizeConst = 64)] string atr, out IntPtr int);
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int getData(IntPtr int, int dataId, byte[] dataBuffer, ref int dataBufferSize);
Run Code Online (Sandbox Code Playgroud)
在 C# 中调用这个方法看起来像这样
static IntPtr number = IntPtr.Zero;
static int res = 0;
try{
number = IntPtr.Zero;
res = find(null, out number);
if (number == IntPtr.Zero)
throw new ApplicationException("Something is wrong");
uint dataBufferSize = 1024;
res = getData(number, 1, null, ref dataBufferSize);
}
Run Code Online (Sandbox Code Playgroud)
我没有找到 Java 中的等价物。
如果我这样做:
public int find(String atr, Pointer int);
Run Code Online (Sandbox Code Playgroud)
它说
java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:419)
at com.sun.jna.Function.invoke(Function.java:354)
at com.sun.jna.Library$Handler.invoke(Library.java:244)
Run Code Online (Sandbox Code Playgroud)
如果我这样做:
public int find(String atr, IntByReference int);
Run Code Online (Sandbox Code Playgroud)
没发生什么事。
Java代码
IntByReference iref = new IntByReference();
res = find(null, iref);
Pointer pointer = iref.getPointer();
int dataBufferSize = 1024;
byte[] dataBuffer = new byte[dataBufferSize];
res = getData(Pointer.nativeValue(pointer), 1, dataBuffer, dataBufferSize);
Run Code Online (Sandbox Code Playgroud)
find 返回 0,表示 OK,而 getData 返回 6,表示内存地址不好。没有任何反应是指除 0 以外的任何其他资源。
IntByReference是可能的正确映射(取决于指针指向的内容);但是,您要查找的值是相应Pointer. 您可能想改用PointerType。无论哪种方式,这Invalid Memory Access都与尝试访问尚未分配的本机端内存有关。plainPointer不会在本机端分配任何内存:通常您会使用 anew Memory()来初始化指针并分配它指向的内存。(如果您创建其中一种ByReference类型,它会在那里分配适当的大小,这就是该错误消失的原因。)
AnIntPtr是一个代表实际内存地址的整数值,您必须使用IntByReferenceor来提取该地址以获取对象,然后将其传递给以返回与您的.PointerTypegetPointer()PointerPointer.nativeValue()longIntPtr
更新以响应您编辑的代码:
一些可能导致问题的错误映射:
for 的签名getData()需要dataBufferSize是对 int 的引用,因此您应该使用IntByReferencefor 该变量。
您无法将普通数组从 Java 传递到本机端。您需要为其分配内存。例如:
Pointer dataBuffer = new Memory(dataBufferSize);
// call getData();
byte[] foo = dataBuffer.getByteArray(0, dataBufferSize);
Run Code Online (Sandbox Code Playgroud)
附加更新:
看起来该方法调用返回一个指向您想要的内存地址的指针,因此您获取find()结果并使用该整数将该整数传递给。IntByReferencefind()getValue()getData()
您可能需要进一步处理生成的byte[]数组。您尚未提供 API 的文档,但如果它返回不同的值,dataBufferSize您可能需要截断字节数组以匹配。由于您IntByReference将传递给的名称命名getData()为iref,因此这将是:
byte[] dataByteArray = new byte[iref.getValue()];
System.arraycopy( dataBuffer, 0, dataByteArray, 0, iref.getValue());
String data = new String(dataByteArray, "UTF-8");
Run Code Online (Sandbox Code Playgroud)
如果 C 字符串的编码方式与 ASCII 不同,您可能需要使用不同的转换。
| 归档时间: |
|
| 查看次数: |
2690 次 |
| 最近记录: |