Windows DXGI Experiment

Jorn Vernee jorn.vernee at oracle.com
Tue Feb 25 16:16:20 UTC 2025


I recommend using the layout as well, rather than messing around with 
ByteBuffer. Jextract [1] can automatically derive that for you, as well 
as some handy setters. That should allow you to define a `DEFINE_GUID` 
method, and then just copy the pre-defined ids from the dxgi.h header 
file (unfortunately, the actual _GUID instances don't seem to be include 
in the dxgi.dll library).

For example, I can use this jextract command to get the basics to call 
the function you're interested in:

$jextract = 'C:\path\to\jextract.ps1'
$I = 'C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0' # for 
example

& $jextract `
   --output src `
   -t org.windows.dxgi `
   -I "$I\shared" `
   -I "$I\ucrt" `
   -I "$I\um" `
   -I "$I\winrt" `
   -l dxgi `
   --include-function CreateDXGIFactory1 `
   --include-struct _GUID `
   --include-typedef IID `
   "<dxgi.h>"

Define the GUID for e.g. IDXGIFactory1:

     // copied from dxgi.h
     static final MemorySegment IID_IDXGIFactory1 = 
DEFINE_GUID(Arena.global(), 
0x770aae78,0xf26f,0x4dba,0xa8,0x29,0x25,0x3c,0x83,0xd1,0xb3,0x87);

     private static MemorySegment DEFINE_GUID(Arena arena, int data1, 
int data2, int data3,
             int data4_0, int data4_1, int data4_2, int data4_3,
             int data4_4, int data4_5, int data4_6, int data4_7) {

         MemorySegment refIID = IID.allocate(arena);
         IID.Data1(refIID, data1);
         IID.Data2(refIID, (short)data2);
         IID.Data3(refIID, (short)data3);

         MemorySegment data4 = IID.Data4(refIID);
         IID.Data4(data4, 0, (byte) data4_0);
         IID.Data4(data4, 1, (byte) data4_1);
         IID.Data4(data4, 2, (byte) data4_2);
         IID.Data4(data4, 3, (byte) data4_3);
         IID.Data4(data4, 4, (byte) data4_4);
         IID.Data4(data4, 5, (byte) data4_5);
         IID.Data4(data4, 6, (byte) data4_6);
         IID.Data4(data4, 7, (byte) data4_7);

         return refIID;
     }

And then it's just a very simple call:

     try (Arena arena = Arena.ofConfined()) {
         MemorySegment factoryPointer =
             arena.allocate(ValueLayout.ADDRESS);

         int hresult = CreateDXGIFactory1(IID_IDXGIFactory1, 
factoryPointer);

         System.out.println(
             "Invocation result: " +
             HexFormat.of().toHexDigits(hresult));
     } catch (Throwable t) {
         t.printStackTrace();
     }

Hope that helps,
Jorn

[1]: https://github.com/openjdk/jextract

On 24-2-2025 19:58, Hugo De Vaan wrote:
> Greetings fellow developers,
>
> I've been trying to create a Java layer atop Microsoft's DXGI library 
> in an attempt to get Java to work with Desktop Duplication. 
> Unfortunately, I can't seem to create a DXGI factory. I can locate the 
> symbol just fine, and I've double checked the UUID value for the type 
> (using an earlier message in this mailing list, dating back to 
> September 2020). When invoking the method handle, I get the 0x80004002 
> HRESULT, which translates to "No such interface supported". I'm not 
> sure what I'm doing wrong here, so I would appreciate any help.
>
> [code]
> import java.lang.foreign.Arena;
> import java.lang.foreign.FunctionDescriptor;
> import java.lang.foreign.Linker;
> import java.lang.foreign.MemorySegment;
> import java.lang.foreign.SymbolLookup;
> import java.lang.foreign.ValueLayout;
> import java.lang.invoke.MethodHandle;
> import java.nio.ByteBuffer;
> import java.nio.ByteOrder;
> import java.util.HexFormat;
>
> public final class DXGIExperiment {
>     public static final void main(String[] args) {
>         try {
>             System.load("C:\\Windows\\System32\\dxgi.dll");
>
>             Linker linker = Linker.nativeLinker();
>
>               SymbolLookup symbols = SymbolLookup.libraryLookup(
>                   "C:\\Windows\\System32\\dxgi.dll", Arena.global());
>
>               /* MemoryLayout BIT128 = MemoryLayout.
>                       sequenceLayout(16, ValueLayout.JAVA_BYTE); */
>
>               /* Giving the 128bit UUID directly to the function doesn't
>                * work - the layout is not supported:
>                *
>                * FunctionDescriptor descriptor = FunctionDescriptor.of(
>                *   ValueLayout.JAVA_INT, BIT128, ValueLayout.ADDRESS);
>                */
>
>               FunctionDescriptor descriptor = FunctionDescriptor.of(
>               ValueLayout.JAVA_INT, ValueLayout.ADDRESS, 
> ValueLayout.ADDRESS);
>
>               MemorySegment createFactory =
>                   symbols.find("CreateDXGIFactory1").get();
>
>              MethodHandle handle = linker.
>                   downcallHandle(createFactory, descriptor);
>
>              System.out.println("Handle to CreateDXGIFactory1 created.");
>
>               byte[] uuidArray = new byte[16];
>               ByteBuffer buffer = ByteBuffer.wrap(uuidArray);
>               buffer.order(ByteOrder.LITTLE_ENDIAN);
>
>               buffer.
>                   putInt(0x770aae78).
>                   putInt(0xf26f4dba).
>                   putInt(0xa829253c).
>                   putInt(0x83d1b387);
>
>               MemorySegment factoryPointer =
>                   Arena.global().allocate(ValueLayout.ADDRESS);
>
>               MemorySegment uuidValue =
>                   Arena.global().allocate(16);
>
>               uuidValue.setAtIndex(ValueLayout.JAVA_INT, 0, 
> buffer.getInt(0));
>               uuidValue.setAtIndex(ValueLayout.JAVA_INT, 1, 
> buffer.getInt(4));
>               uuidValue.setAtIndex(ValueLayout.JAVA_INT, 2, 
> buffer.getInt(8));
>               uuidValue.setAtIndex(ValueLayout.JAVA_INT, 3, 
> buffer.getInt(12));
>
>               int hresult = (int) handle.
>                   invokeExact(uuidValue, factoryPointer);
>
>               System.out.println(
>                   "Invocation result: " +
>                   HexFormat.of().toHexDigits(hresult));
>               } catch (Throwable t) {
>                   t.printStackTrace();
>               }
>       }
> }
> [/code]
>
> PS: This was tried on Windows 10 Pro, 64 bit, build 19045 and running 
> GraalVM 21+35.1
>
> Regards,
> Hugo


More information about the panama-dev mailing list