将数据从 DLL 复制到 ByteBuffer (JNA)

Copying data from a DLL to a ByteBuffer (JNA)

我正在将使用 ctypes 的 Python 脚本移植到 Java。

脚本的一部分将数据从 DLL 的虚拟内存复制到缓冲区,该缓冲区存储所述数据以供稍后复制回来。我不确定如何在 JNA 中完成此操作。

我确实有存储我想要的数据的虚拟地址的确切值,但我不确定如何获取指向这些虚拟地址的指针,因为 JNA 的 Javadoc 从未指定指针是相对于系统内存还是 DLL 内存。

如何将指针设置为指向 Java 中的指定(虚拟)内存地址?在 Python 中,可以使用 dll._handle + address.

设置正确的值

JNA 的 Pointer class 间接(全局)系统内存,相当于 C 的 &foo 符号指向 foo 的唯一、全局、系统范围的内存地址.

class 有一个 Pointer(long peer) 构造函数,它将实际的本机内存地址作为参数。 (您也可以使用 Pointer.nativeValue() 提取此值。)这通常不需要,因为用户通常不必担心特定的内存地址。正如 Javadoc 所述:

Don't use this unless you know what you're doing.

除此之外,如果您需要一个相对于其他基点的虚拟地址,您需要找到合适的特定于平台的函数,它可以为您识别该本地指针地址。例如,在 Windows 中,您将使用 GetModuleInformation(). This is mapped in the user-contributed JNA mappings (jna-platform artifact) in the Psapi interface, or you can map it yourself. The MODULEINFO structure you get using that method will contain the starting address for the DLL, and you can add an offset, although it appears to be identical to the HMODULE input, so perhaps all you need to call is EnumProcessModules(). This other answer 提供执行此操作所需的代码(尽管我会使用 long 来表示 64 位指针)。

注意 JNA 的 Psapi 中的 cautions in the Javadoc class:

If the module list in the target process is corrupted or not yet initialized, or if the module list changes during the function call as a result of DLLs being loaded or unloaded, EnumProcessModules may fail or return incorrect information.

这里还有很多注意事项。

更新: 根据您的评论,加载的 DLL 的 handle 暴露在库的 toString() 中。例如:

Kernel32 foo = Kernel32.INSTANCE;
System.out.println(foo.toString());

将return

Proxy interface to Native Library kernel32.dll@140737217757184

再说一次,“除非你知道自己在做什么,否则不要使用它。”