在JNA中,GlobalAlloc和GlobalLock的返回值有什么不同

What is the difference of return value between GlobalAlloc And GlobalLock in JNA

本文关键字:返回值 什么 GlobalLock JNA GlobalAlloc      更新时间:2023-10-16

当我使用jna时,GlobalAlloc和GlobalLock都会返回Pointer,但我发现它们的表现好像不相等。

例如,

在下面的这个案例中,我发现TestStructure的实例是没有达到我所期望的状态。

Kernel32 kernel32 = Native.loadLibrary("kernel32",Kernel32.class);
Pointer pointer = kernel32.GlobalAlloc(ghnd, size);
Pointer pointer2 = kernel32.GlobalLock(pointer);
pointer2.write(0, testbyte, 0, dmSize);
TestStructure structure = new TestStructure(pointer);

但下面的情况很好。

Kernel32 kernel32 = Native.loadLibrary("kernel32",Kernel32.class);
Pointer pointer = kernel32.GlobalAlloc(ghnd, size);
Pointer pointer2 = kernel32.GlobalLock(pointer);
pointer2.write(0, testbyte, 0, dmSize);
TestStructure structure = new TestStructure(pointer2);

为什么我必须使用pointer2实例来创建TestStructure。我认为指针和指针2应该指向同一个位置。

//添加2015.04.03

1是的,我在Windows平台上工作。

2测试结构见下文。

public class TestStructure extends Structure {
  public char[] dmDeviceName = new char[32];
  public WORD dmSpecVersion;
  public WORD dmDriverVersion;
  public WORD dmSize;
  public WORD dmDriverExtra;
  public DWORD dmFields;
  public UnionField1 unionField1;
  public short dmColor;
  public short dmDuplex;
  public short dmYResolution;
  public short dmTTOption;
  public short dmCollate;
  public char[] dmFormname = new char[32];
  public WORD dmLogPixels;
  public DWORD dmBitsPerpel;
  public DWORD dmPelsWidth;
  public DWORD dmPelsHeight;
  public UnionField2 unionField2;
  public DWORD dmDisplayFrequency;
  public TestStructure(Pointer pointer) {
    useMemory(pointer);
    read();
  }
  @Override
  protected List getFieldOrder() {
    return Arrays.asList(new String[] { "dmDeviceName", "dmSpecVersion", "dmDriverVersion", "dmSize",
            "dmDriverExtra", "dmFields", "unionField1", "dmColor", "dmDuplex", "dmYResolution", "dmTTOption",
            "dmCollate", "dmFormname", "dmLogPixels", "dmBitsPerpel", "dmPelsWidth", "dmPelsHeight", "unionField2",
            "dmDisplayFrequency" });
  }
}    

我假设您在Windows平台上工作。GlobalXx函数实际上是对旧的16位Windows的回忆。在那个(旧)时代,GlobalAlloc用来返回一个(16位)句柄,该句柄是GlobalLock转换为32位指针的。

如果您使用GHND=0x42作为第一个参数来请求一个可移动的内存块,您仍然可以表现出类似的行为。如果执行GlobalAlloc,则返回一个(32位)句柄,该句柄必须转换为具有GlobalLock的真指针。可以在对GlobalLock-GlobalUnlock的不同调用之间为存储器块分配不同的指针值。

MSDN中的页面状态注意全局函数比其他内存管理函数具有更大的开销和更少的功能。新的应用程序应该使用堆函数,除非文档说明应该使用全局函数这意味着MicroSoft建议使用HeapAlloc系列函数,除非您需要使用GlobalAlloc

MSDN中的参考文献:GlobalAlloc函数比较内存分配方法