Search code examples
javac++jna

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


When I'm using jna, both GlobalAlloc And GlobalLock returns Pointer, but I found both of them performing as if they are not equal.

For example,

On this case below, I found instance of TestStructure is not in proper state which I expected.

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

but the case below working fine.

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

Why do I have to use pointer2 instance to create TestStructure. I think both pointer and pointer2 should points same place.

//add 2015.04.03

1 Yes, I'm working on Windows Platform.

2 See below for TestStrucure.

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

Solution

  • I assume you are working on a Windows platform. The GlobalXx functions are in fact a reminiscence of old 16 bits Windows. In that (old) time, GlobalAlloc used to return a (16 bits) handle that was converter to a 32 bits pointer by GlobalLock.

    You can still exhibit similar behaviour if you ask for a movable memory block, by using GHND = 0x42 as first parameter. If you do GlobalAlloc returns a (32 bits) handle that must be converted into a true pointer with GlobalLock. The memory block can be assigned different pointer values across different calls to GlobalLock - GlobalUnlock.

    The page in MSDN states Note The global functions have greater overhead and provide fewer features than other memory management functions. New applications should use the heap functions unless documentation states that a global function should be used. That means that MicroSoft advices to use HeapAlloc serie functions instead, unless you are required to use GlobalAlloc.

    References from the MSDN : GlobalAlloc function Comparing Memory Allocation Methods