Error Running jextract on d3d12.h

Michael Ennen mike.ennen at gmail.com
Tue Sep 15 17:53:21 UTC 2020


Shoot, I should have realized that from the earlier examples. It needs the
(this) pointer basically. Yes, I forgot that.

Well thanks so much for everything.

I figured there would be a lot of redundancies and ugly Java style as it
was more exploratory, but having cleaner code
at any stage is a huge bonus.

Alright! Awesome! Much to review here and soak in.

Thanks so much.

On Tue, Sep 15, 2020 at 10:35 AM Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:

> After throwing the kitchen sink at your example (I set up Windows on a
> virtual instance to play with it), I was able to reproduce the issue.
>
> I discussed this with Jorn offline and Jorn pointed out at an issue that
> I should have spotted much earlier (thanks!) - the issue is that when
> looking at API docs like:
>
>
> https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createcommandqueue
>
> This is actually the description of the C++ API.
>
> The C API almost always takes some extra parameter - in the case of this
> function, the first parameter must be a device pointer.
>
> Here's the rewritten example (I took the liberty to streamline the Java
> code a bit, I hope you don't mind):
>
> public class Main {
>
>      public enum IID {
>          IID_IDXGIAdapter1(0x29038f61, 0x3839, 0x4626, 0x91, 0xfd, 0x08,
> 0x68, 0x79, 0x01, 0x1a, 0x05),
>          IID_IDXGIFactory1(0x770aae78, 0xf26f, 0x4dba, 0xa8, 0x29, 0x25,
> 0x3c, 0x83, 0xd1, 0xb3, 0x87),
>          IID_ID3D12Device(0x189819f1, 0x1db6, 0x4b57, 0xbe, 0x54, 0x18,
> 0x21, 0x33, 0x9b, 0x85, 0xf7),
>          IID_ID3D12CommandQueue(0x0ec870a6, 0x5d7e, 0x4c22, 0x8c, 0xfc,
> 0x5b, 0xaa, 0xe0, 0x76, 0x16, 0xed);
>
>          final MemorySegment guid;
>
>          IID(int data1, int data2, int data3, int... data4) {
>              MemorySegment segment =
> MemorySegment.allocateNative(guiddef_h.GUID.$LAYOUT());
>              GUID.Data1$set(segment, data1);
>              GUID.Data2$set(segment, (short)data2);
>              GUID.Data3$set(segment, (short)data3);
>              MemorySegment data4_segment = GUID.Data4$slice(segment);
>              for (int i = 0 ; i < data4.length ; i++) {
>                  MemoryAccess.setByteAtIndex(data4_segment, i,
> (byte)data4[i]);
>              }
>              this.guid = segment;
>          }
>      }
>
>      public static void main(String[] args) throws Throwable {
>          try (NativeScope scope = NativeScope.unboundedScope()) {
>              // IDXGIFactory1** dxgiFactory;
>              var ppDxgiFactory = IDXGIFactory1.allocatePointer(scope);
>              // HRESULT = CreateDXGIFactory1(_uuid(dxgiFactory),
> &dxgiFactory))
> checkResult(dxgi_h.CreateDXGIFactory1(IID.IID_IDXGIFactory1.guid,
> ppDxgiFactory));
>              // IDXGIFactory1*
>              MemorySegment pDxgiFactory =
> IDXGIFactory1.ofAddressRestricted(MemoryAccess.getAddress(ppDxgiFactory));
>
>              // (This)->lpVtbl
>              MemorySegment vtbl =
>
> IDXGIFactory1Vtbl.ofAddressRestricted(IDXGIFactory1.lpVtbl$get(pDxgiFactory));
>              // lpVtbl->EnumAdapters1
>              MemoryAddress addrEnumAdapters =
> IDXGIFactory1Vtbl.EnumAdapters1$get(vtbl);
>
>              // link the pointer
>              MethodHandle MH_EnumAdapters1 =
> getSystemLinker().downcallHandle(
>                      addrEnumAdapters,
>                      MethodType.methodType(int.class,
> MemoryAddress.class, int.class, MemoryAddress.class),
>                      FunctionDescriptor.of(C_INT, C_POINTER, C_INT,
> C_POINTER));
>
>              /* [annotation][out] _COM_Outptr_  IDXGIAdapter1** */
>              MemorySegment ppOut = IDXGIAdapter1.allocatePointer(scope);
>              checkResult((int)
> MH_EnumAdapters1.invokeExact(pDxgiFactory.address(), 0, ppOut.address()));
>              // IDXGIAdapter1*
>              MemorySegment pAdapter =
> IDXGIAdapter1.ofAddressRestricted(MemoryAccess.getAddress(ppOut));
>
>              // (This)->lpVtbl
>              MemorySegment vtbl2 =
> IDXGIAdapter1Vtbl.ofAddressRestricted(IDXGIAdapter1.lpVtbl$get(pAdapter));
>              // lpVtbl->EnumAdapters1
>              // HRESULT(*)(IDXGIAdapter1*,DXGI_ADAPTER_DESC1*)
>              MemoryAddress addrGetDesc1 =
> IDXGIAdapter1Vtbl.GetDesc1$get(vtbl2);
>
>              // link the pointer
>              MethodHandle MH_GetDesc1 = getSystemLinker().downcallHandle(
>                      addrGetDesc1,
>                      MethodType.methodType(int.class,
> MemoryAddress.class, MemoryAddress.class),
>                      FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER));
>
>              /* DXGI_ADAPTER_DESC1* */
>              MemorySegment pDesc = DXGI_ADAPTER_DESC1.allocate(scope);
>              checkResult((int)
> MH_GetDesc1.invokeExact(pAdapter.address(), pDesc.address()));
>
>              // print description
>              MemorySegment descStr =
> DXGI_ADAPTER_DESC1.Description$slice(pDesc);
>              String str = new String(descStr.toByteArray(),
> StandardCharsets.UTF_16LE);
>              System.out.println(str);
>
>              //D3D12CreateDevice$MH()
>              // ID3D12Device** d3d12Device;
>              var ppDevice = ID3D12Device.allocatePointer(scope);
>
>              // D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0,
> IID_PPV_ARGS(&ppDevice))
>              checkResult(D3D12CreateDevice(pAdapter, (int) 45056L,
> IID.IID_ID3D12Device.guid, ppDevice));
>              // ID3D12Device*
>              MemorySegment pDevice =
> ID3D12Device.ofAddressRestricted(MemoryAccess.getAddress(ppDevice));
>
>              // (This)->lpVtbl
>              MemorySegment deviceVtbl =
> ID3D12DeviceVtbl.ofAddressRestricted(ID3D12Device.lpVtbl$get(pDevice));
>
>              // lpVtbl->CreateCommandQueue
>              MemoryAddress addrCreateCommandQueue =
> ID3D12DeviceVtbl.CreateCommandQueue$get(deviceVtbl);
>
>              // D3D12_COMMAND_QUEUE_DESC queueDesc = {};
>              // queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
>              // queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
>              MemorySegment pQueueDesc =
> D3D12_COMMAND_QUEUE_DESC.allocate(scope);
>              //MemorySegment queueDesc = asSegment(pQueueDesc.address(),
> D3D12_COMMAND_QUEUE_DESC.$LAYOUT());
>              D3D12_COMMAND_QUEUE_DESC.Type$set(pQueueDesc,
> D3D12_COMMAND_LIST_TYPE_DIRECT());
>              D3D12_COMMAND_QUEUE_DESC.Flags$set(pQueueDesc,
> D3D12_COMMAND_QUEUE_FLAG_NONE());
>
>              // link the pointer
>              MethodHandle MH_ID3D12Device_CreateCommandQueue =
> getSystemLinker().downcallHandle(
>                      addrCreateCommandQueue,
>                      MethodType.methodType(int.class,
> MemoryAddress.class, MemoryAddress.class, MemoryAddress.class,
> MemoryAddress.class),
>                      FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER,
> C_POINTER, C_POINTER));
>
>              var ppQueue = ID3D12CommandQueue.allocatePointer(scope);
>
>              checkResult((int)
> MH_ID3D12Device_CreateCommandQueue.invokeExact(pDevice.address(),
> pQueueDesc.address(),
>                      IID.IID_ID3D12CommandQueue.guid.address(),
> ppQueue.address()));
>          }
>      }
>
>      private static final int S_OK = 0x00000000;
>
>      private static void checkResult(int result) {
>          switch (result) {
>              case S_OK -> {}
>              default -> throw new IllegalStateException("Unknown result:
> " + String.format("%X8", result));
>          }
>      }
> }
>
>
> Cheers
> Maurizio
>
> On 15/09/2020 11:12, Maurizio Cimadamore wrote:
> > Hi Michael,
> > You are trying to put a fairly complex example together using the
> > foreign API so (1) thanks for sticking with it and (2) there's no harm
> > in asking :-)
> >
> > Again, big disclaimer - I'm not on Windows, so I can't test it out -
> > here are some comments from eyeballing your code (although, I can't
> > see anything particularly wrong). The one thing I initially focussed
> > on was this:
> >
> > var ppQueue = ID3D12CommandQueue.allocatePointer(scope);
> >
> > This will allocate a 64-bit long memory segment (enough to contain a
> > pointer). But the contents will be blank. But I think this is ok, as
> > the API is probably meant to fill in the pointer to the newly
> > allocated command queue area (e.g. output parameter idiom).
> >
> > Another thing I noticed is that you do things like:
> >
> >> MemorySegment pQueueDesc = D3D12_COMMAND_QUEUE_DESC.allocate(scope);
> >> MemorySegment queueDesc = asSegment(pQueueDesc.address(),
> >> D3D12_COMMAND_QUEUE_DESC.$LAYOUT()); // <--------
> >> D3D12_COMMAND_QUEUE_DESC.Type$set(queueDesc,
> >> D3D12_COMMAND_LIST_TYPE_DIRECT());
> >> D3D12_COMMAND_QUEUE_DESC.Flags$set(queueDesc,
> >> D3D12_COMMAND_QUEUE_FLAG_NONE());
> >>
> >
> > I find the second instruction above redundant here. You already have a
> > fully readable/writable segment for the struct, you don't need to go
> > to the extra jump of re-creating another segment from its address. You
> > can just remove that second line and just use pQueueDesc in the two
> > set operations. In other words, you should only use `asSegment` if you
> > get a MemoryAddress from the library, but you want to turn it into a
> > memory segment with certain known size (so that you can read and write
> > from it).
> >
> >
> > Looking at the GUID function, I also see some issues:
> >
> >> MemorySegment segment = MemorySegment.allocateNative(GUID.map(l ->
> >> ((SequenceLayout) l).withElementCount(8),
> >> MemoryLayout.PathElement.groupElement("Data4")));
> >>
> >>
> > This doesn't seem to do anything - the layout you start with already
> > has a sequence layout with 8 elements in "Data4", so you are just
> > replacing that sequence layout with another identical one. That said,
> > this is just a stylistic issue, the main logic of the code seems to be
> > correct in initializing the contents of the segment (you could use, if
> > you wanted a bulk copy to transfer the byte array into "Data4"
> > directly, but that's not necessary to get correctness - can be
> > improved later).
> >
> >
> > Another Java-style comment - you have an Enum defining various IIDs -
> > and then you have a unique mapping between an IID and a segment. I
> > wonder if the MemorySegment could become a field of the IID enum - so
> > that you don't even need the map.
> >
> >
> > That said, I can't find anything obviously "wrong" with your usage of
> > this DX12 API - I've gone back and forth between code and API docs
> > several times to check the various structures and pointers you pass,
> > but it all looks ok. Are you 100% sure that the crash happens in the
> > invokeExact to the CreateCommandQueue? That could suggest one of the
> > following:
> >
> > 1) the descriptor you use for linking the function is wrong (e.g.
> > wrong argument arity, types) - that doesn't seem to be the case
> > 2) the arguments you are passing are wrong (e.g. unitialized
> > args/pointers) - again, this doesn't seem to be the case
> > 3) the function pointer itself being linked is wrong - this I have no
> > way to verify
> >
> > I think it would help to get "crash log" from the VM; that will
> > contain extra stack information, such as what exactly the thread was
> > doing when the VM crashed - this could tell us for instance if the
> > crash occurred inside the dx12 library, or if we didn't even get there
> > - which would suggest that the function pointer to CreateCommandQueue
> > is wrong somehow.
> >
> >
> > I hope this helps a bit. I'm sure we're close.
> >
> > Cheers
> > Maurizio
> >
> >
> >
> >
> >
> > On 15/09/2020 00:05, Michael Ennen wrote:
> >> At this point I may be beating a dead horse and should be able to
> >> figure this out from the awesome example you provided but
> >> in the case of using "invokeExact" on a MethodHandle, how can one, in
> >> that case, send a GUID as an argument?
> >>
> >> That is for a global function it was done thusly:
> >>
> >> checkResult(dxgi_h.CreateDXGIFactory1(GUID(IID.IID_IDXGIFactory1),
> >> ppDxgiFactory));
> >>
> >> In the case of "invokeExact" it needs a MemoryAddress so I figured it
> >> would just be:
> >>
> >>      checkResult((int)
> >>
> MH_ID3D12Device_CreateCommandQueue.invokeExact(pQueueDesc.address(),GUID(IID.IID_ID3D12CommandQueue).address(),
>
> >> ppQueue.address()));
> >>
> >> But I am getting an access violation.
> >>
> >> I am trying to extend the example to create an ID3D12Device and
> >> ID3D12CommandQueue thusly:
> >>
> >> //D3D12CreateDevice$MH()
> >> // ID3D12Device** d3d12Device;
> >> var ppDevice = ID3D12Device.allocatePointer(scope);
> >>
> >> // D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0,
> >> IID_PPV_ARGS(&ppDevice))
> >> checkResult(D3D12CreateDevice(pAdapter, (int) 45056L,
> >> GUID(IID.IID_ID3D12Device), ppDevice));
> >> // ID3D12Device*
> >> MemorySegment pDevice = asSegment(MemoryAccess.getAddress(ppDevice),
> >> ID3D12Device.$LAYOUT());
> >>
> >> // (This)->lpVtbl
> >> MemorySegment deviceVtbl =
> >> asSegment(ID3D12Device.lpVtbl$get(pDevice), ID3D12DeviceVtbl.$LAYOUT());
> >>
> >> // lpVtbl->CreateCommandQueue
> >> MemoryAddress addrCreateCommandQueue =
> >> ID3D12DeviceVtbl.CreateCommandQueue$get(deviceVtbl);
> >>
> >> // D3D12_COMMAND_QUEUE_DESC queueDesc = {};
> >> // queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
> >> // queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
> >> MemorySegment pQueueDesc =  D3D12_COMMAND_QUEUE_DESC.allocate(scope);
> >> MemorySegment queueDesc = asSegment(pQueueDesc.address(),
> >> D3D12_COMMAND_QUEUE_DESC.$LAYOUT());
> >> D3D12_COMMAND_QUEUE_DESC.Type$set(queueDesc,
> >> D3D12_COMMAND_LIST_TYPE_DIRECT());
> >> D3D12_COMMAND_QUEUE_DESC.Flags$set(queueDesc,
> >> D3D12_COMMAND_QUEUE_FLAG_NONE());
> >>
> >> // link the pointer
> >> MethodHandle MH_ID3D12Device_CreateCommandQueue =
> >> getSystemLinker().downcallHandle(
> >> addrCreateCommandQueue,
> >> MethodType.methodType(int.class, MemoryAddress.class,
> >> MemoryAddress.class, MemoryAddress.class),
> >> FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER, C_POINTER));
> >>
> >> var ppQueue = ID3D12CommandQueue.allocatePointer(scope);
> >>
> >> checkResult((int)
> >> MH_ID3D12Device_CreateCommandQueue.invokeExact(pQueueDesc.address(),
> >> GUID(IID.IID_ID3D12CommandQueue).address(), ppQueue.address()));
> >>
> >> Full example here:
> >>
> >>
> https://github.com/brcolow/java-dx12/blob/master/src/main/java/com/dx12/DX12.java
> >> <
> https://urldefense.com/v3/__https://github.com/brcolow/java-dx12/blob/master/src/main/java/com/dx12/DX12.java__;!!GqivPVa7Brio!NNn4WtIsLKjlTcTCh-TY2gYE6mbNNXrzVKMHA4rEupoedndflmeMdLXktTMoasJKTw999Fs$>
>
> >>
> >>
> >> Sorry if it's painfully obvious, this is the last question on this
> >> topic I will ask!
> >>
> >> On Mon, Sep 14, 2020 at 11:45 AM Jorn Vernee <jorn.vernee at oracle.com
> >> <mailto:jorn.vernee at oracle.com>> wrote:
> >>
> >>     Hi Michael,
> >>
> >>     Note that I passed -l dxgi to jextract when extracting dxgi.h,
> >>     that will making it so the dxgi library is used to link the
> >>     functions. d3d12 didn't seem to be needed. Doing that should avoid
> >>     the need to manually load the library like you've shown.
> >>
> >>     This is what I ended up with:
> >>
> >>     $jdk = ...
> >>     nal -Name jextract -Value "$jdk\bin\jextract.exe"
> >>     $I = "C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0"
> >>     jextract -d out -t org.jextract --filter "dxgi.h" -l dxgi --
> >>     "$I\shared\dxgi.h"
> >>     jextract -d out -t org.jextract --filter "guiddef.h" --
> >>     "$I\shared\guiddef.h"
> >>     jar -cf dxgi.jar -C out org
> >>
> >>     Jorn
> >>
> >>     On 14/09/2020 19:51, Michael Ennen wrote:
> >>>     It worked for me! Awesome!
> >>>
> >>>     One quick question:
> >>>
> >>>     I had to add the following:
> >>>
> >>>             LibraryLookup d3d12 = LibraryLookup.ofLibrary("D3D12");
> >>>             LibraryLookup dxgi = LibraryLookup.ofLibrary("dxgi");
> >>>
> >>>     To get the methods to be wired up, is that expected? I don't see
> >>>     it in your example.
> >>>
> >>>     Thanks again *so much*. This is a fantastic reference to get
> >>>     started as it handles some complexities like function
> >>>     pointers and the complexities of having a C API that really
> >>>     corresponds to a C++ API which seems to be the case
> >>>     with DirectX12.
> >>>
> >>>     On Mon, Sep 14, 2020 at 10:39 AM Michael Ennen
> >>>     <mike.ennen at gmail.com <mailto:mike.ennen at gmail.com>> wrote:
> >>>
> >>>         Ahhh, this makes so much more sense now.
> >>>
> >>>         Thank you both tremendously.
> >>>
> >>>         On Mon, Sep 14, 2020 at 6:39 AM Jorn Vernee
> >>>         <jorn.vernee at oracle.com <mailto:jorn.vernee at oracle.com>>
> wrote:
> >>>
> >>>             Ok, it looks like the formatting got messed up in the
> >>>             email, so I've
> >>>             uploaded the example here as well:
> >>>
> >>> http://cr.openjdk.java.net/~jvernee/d3d12_example/Main.java
> >>>
> >>>             Jorn
> >>>
> >>>             On 14/09/2020 15:28, Jorn Vernee wrote:
> >>>             > I've tried it out on my machine as well (I'm also on
> >>>             Windows). Here is
> >>>             > a little bit more complete example that prints out the
> >>>             adapter
> >>>             > description
> >>>             >
> >>>             > If you have extracted the shared/dxgi.h and the
> >>>             shared/guiddef.h
> >>>             > headers as well, you can do something like this:
> >>>             >
> >>>             >
> >>>             > import jdk.incubator.foreign.FunctionDescriptor;
> >>>             > import jdk.incubator.foreign.MemoryAccess;
> >>>             > import jdk.incubator.foreign.MemoryAddress;
> >>>             > import jdk.incubator.foreign.MemoryLayout;
> >>>             > import jdk.incubator.foreign.MemorySegment;
> >>>             > import jdk.incubator.foreign.NativeScope;
> >>>             > import org.jextract.dxgi_h;
> >>>             > import org.jextract.guiddef_h;
> >>>             >
> >>>             > import java.lang.invoke.MethodHandle;
> >>>             > import java.lang.invoke.MethodType;
> >>>             > import java.nio.charset.StandardCharsets;
> >>>             >
> >>>             > import static jdk.incubator.foreign.CSupport.*;
> >>>             > import static org.jextract.dxgi_h.*;
> >>>             >
> >>>             > public class Main {
> >>>             >
> >>>             >     public static void main(String[] args)throws
> >>>             Throwable {
> >>>             >         try (NativeScope scope
> >>>             =NativeScope.unboundedScope()) {
> >>>             >             // IDXGIFactory1** dxgiFactory;
> >>>             > var ppDxgiFactory =IDXGIFactory1.allocatePointer(scope);
> >>>             >             // HRESULT =
> >>>             CreateDXGIFactory1(_uuid(dxgiFactory),
> >>>             > &dxgiFactory))
> >>>             >
> >>>
> checkResult(dxgi_h.CreateDXGIFactory1(IID_IDXGIFactory1,ppDxgiFactory));
> >>>
> >>>             >             // IDXGIFactory1* MemorySegment pDxgiFactory
> >>>             >
> >>>
> =asSegment(MemoryAccess.getAddress(ppDxgiFactory),IDXGIFactory1.$LAYOUT());
> >>>             >
> >>>             >             // (This)->lpVtbl MemorySegment vtbl
> >>>             >
> >>>
> =asSegment(IDXGIFactory1.lpVtbl$get(pDxgiFactory),IDXGIFactory1Vtbl.$LAYOUT());
> >>>             >             // lpVtbl->EnumAdapters1 MemoryAddress
> >>>             addrEnumAdapters
> >>>             > =IDXGIFactory1Vtbl.EnumAdapters1$get(vtbl);
> >>>             >
> >>>             >             // link the pointer MethodHandle
> >>>             MH_EnumAdapters1
> >>>             > =getSystemLinker().downcallHandle(
> >>>             >                 addrEnumAdapters,
> >>>             >
> >>>
> MethodType.methodType(int.class,MemoryAddress.class,int.class,MemoryAddress.class),
> >>>             > FunctionDescriptor.of(C_INT,C_POINTER,C_INT,C_POINTER));
> >>>             >
> >>>             >             /* [annotation][out] _COM_Outptr_
> >>>             IDXGIAdapter1** */
> >>>             > MemorySegment ppOut
> >>> =IDXGIAdapter1.allocatePointer(scope);
> >>>             >
> >>>
> checkResult((int)MH_EnumAdapters1.invokeExact(pDxgiFactory.address(),0,ppOut.address()));//
> >>>
> >>>             > IDXGIAdapter1* MemorySegment pAdapter
> >>>             >
> >>> =asSegment(MemoryAccess.getAddress(ppOut),IDXGIAdapter1.$LAYOUT());
> >>>             >
> >>>             >             // (This)->lpVtbl MemorySegment vtbl2
> >>>             >
> >>>
> =asSegment(IDXGIAdapter1.lpVtbl$get(pAdapter),IDXGIAdapter1Vtbl.$LAYOUT());
> >>>             >             // lpVtbl->EnumAdapters1 //
> >>>             > HRESULT(*)(IDXGIAdapter1*,DXGI_ADAPTER_DESC1*)
> >>>             MemoryAddress
> >>>             > addrGetDesc1 =IDXGIAdapter1Vtbl.GetDesc1$get(vtbl2);
> >>>             >
> >>>             >             // link the pointer MethodHandle MH_GetDesc1
> >>>             > =getSystemLinker().downcallHandle(
> >>>             >                 addrGetDesc1,
> >>>             >
> >>>
> MethodType.methodType(int.class,MemoryAddress.class,MemoryAddress.class),
> >>>             > FunctionDescriptor.of(C_INT,C_POINTER,C_POINTER));
> >>>             >
> >>>             >             /* DXGI_ADAPTER_DESC1* */ MemorySegment pDesc
> >>>             > =DXGI_ADAPTER_DESC1.allocate(scope);
> >>>             >
> >>>
> checkResult((int)MH_GetDesc1.invokeExact(pAdapter.address(),pDesc.address()));
> >>>             >
> >>>             >             // print description MemorySegment descStr
> >>>             > =DXGI_ADAPTER_DESC1.Description$slice(pDesc);
> >>>             >             String str =new
> >>>             > String(descStr.toByteArray(),StandardCharsets.UTF_16LE);
> >>>             >             System.out.println(str);
> >>>             >         }
> >>>             >     }
> >>>             >
> >>>             >     public static MemorySegment asSegment(MemoryAddress
> >>>             > addr,MemoryLayout layout) {
> >>>             >         return MemorySegment.ofNativeRestricted(addr,
> >>>             > layout.byteSize(),Thread.currentThread(),null,null);
> >>>             >     }
> >>>             >
> >>>             >     static final MemorySegment IID_IDXGIFactory1 =GUID(
> >>>             >             (int)0x770aae78,
> >>>             >             (short)0xf26f,
> >>>             >             (short)0x4dba,
> >>>             >             new byte[]{(byte)0xa8,0x29,0x25,0x3c,
> >>>             (byte)0x83,
> >>>             > (byte)0xd1, (byte)0xb3, (byte)0x87});
> >>>             >
> >>>             >     static final MemorySegment GUID(int Data1,short
> >>>             Data2,short
> >>>             > Data3,byte[] Data4) {
> >>>             >         MemorySegment ms
> >>>             > =MemorySegment.allocateNative(guiddef_h.GUID.$LAYOUT());
> >>>             >         guiddef_h.GUID.Data1$set(ms, Data1);
> >>>             >         guiddef_h.GUID.Data2$set(ms, Data2);
> >>>             >         guiddef_h.GUID.Data3$set(ms, Data3);
> >>>             >
> >>> guiddef_h.GUID.Data4$slice(ms).copyFrom(MemorySegment.ofArray(Data4));
> >>>             >         return ms;
> >>>             >     }
> >>>             >
> >>>             >     private static final int S_OK =0x00000000;
> >>>             >
> >>>             >     private static void checkResult(int result) {
> >>>             >         switch (result) {
> >>>             >             case S_OK -> {}
> >>>             >             default ->throw new
> >>>             IllegalStateException("Unknown result:
> >>>             > " +String.format("%X8", result));
> >>>             >         }
> >>>             >     }
> >>>             > }
> >>>             >
> >>>             >
> >>>             > Which on my machine prints: NVIDIA GeForce GTX 1050 Ti
> >>>             >
> >>>             > HTH,
> >>>             > Jorn
> >>>             >
> >>>             > On 14/09/2020 12:52, Maurizio Cimadamore wrote:
> >>>             >> I think there's something off in here:
> >>>             >>
> >>>             >>> MemorySegment segment =
> >>>             >>>
> >>>
> MemorySegment.allocateNative(dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize());
> >>>
> >>>             >>>
> >>>             >>> MemoryAddress address =
> >>> segment.address().addOffset(64);
> >>>             >> I see a couple of issues:
> >>>             >>
> >>>             >> 1) how do you determine that the offset of the
> >>>             function address you
> >>>             >> want to obtain is 64 byte from the start? Didn't
> >>>             jextract give you a
> >>>             >> getter for that?
> >>>             >>
> >>>             >> 2) Even assuming 64 byte is the correct offset, note
> >>>             that the segment
> >>>             >> will be initialized to all zeros - I presume this
> >>>             vtable must be
> >>>             >> filled in somehow, or perhaps obtained from a global
> >>>             variable?
> >>>             >>
> >>>             >> From your earlier email I see this:
> >>>             >>
> >>>             >>> interface IDXGIFactory
> >>>             >>>       {
> >>>             >>>           CONST_VTBL struct IDXGIFactoryVtbl *lpVtbl;
> >>>             >>>       };
> >>>             >> So... perhaps once yo create a IDXGIFactory, you can
> >>>             just grab the
> >>>             >> pointer to the vtable by accessing its `lpVtbl` field
> >>>             - no need to
> >>>             >> allocate a new segment (the library has done the
> >>>             allocation for you).
> >>>             >>
> >>>             >> If I'm correct, this can be achieved with something
> >>>             like (not sure if
> >>>             >> the names are going to be 100% correct since I don't
> >>>             have a
> >>>             >> jextracted version of the API with me - so beware, I
> >>>             have NOT tested
> >>>             >> this :-) ):
> >>>             >>
> >>>             >> var dxgiFactoryPtr =
> >>>             >>
> >>> MemoryAccess.getAddress(MemorySegment.ofNativeRestricted(),
> >>>             >> dxgiFactory);
> >>>             >> var lpVtbl =
> >>>             >>
> >>> MemoryAccess.getAddress(MemorySegment.ofNativeRestricted(),
> >>>             >> dxgiFactoryPtr);
> >>>             >> var vtable = RuntimeHelper.ofArrayRestricted(lpVtbl,
> >>>             >> IDXGIFactory1Vtbl.$LAYOUT(), 1); //1
> >>>             >> var address =
> >>> IDXGIFactory1Vtbl$EnumAdapters$get(vtable);
> >>>             >>
> >>>             >>
> >>>             >> And this should give the address pointer you are
> >>>             looking for. We need
> >>>             >> to smooth the edges especially around (1) - e.g. to
> >>>             turn a random
> >>>             >> native pointer into a struct with given layout
> >>>             (jextract should
> >>>             >> generate a static helper for that, see [1]) - but with
> >>>             the code above
> >>>             >> you should be able to get there, I hope.
> >>>             >>
> >>>             >> P.S.
> >>>             >> In these situations, my suggestion is, especially when
> >>>             attacking a
> >>>             >> native library for the first time, to always try the
> >>>             library directly
> >>>             >> using C and see what happens, to understand exactly
> >>>             what kind of
> >>>             >> pattern/idiom the library requires. I did that many
> >>>             times and
> >>>             >> realized my assumptions on how library worked were
> >>>             wrong; other users
> >>>             >> have posted similar instances in this mailing list.
> >>>             Once you get
> >>>             >> things working in C, porting the code in Java using
> >>>             the Panama API is
> >>>             >> typically a trivial matter.
> >>>             >>
> >>>             >> Maurizio
> >>>             >>
> >>>             >> [1] - https://bugs.openjdk.java.net/browse/JDK-8253102
> >>>             >>
> >>>             >>
> >>>             >> On 13/09/2020 02:37, Michael Ennen wrote:
> >>>             >>> Well, progress of a kind? This crashes the VM instead
> >>>             of not
> >>>             >>> compiling or
> >>>             >>> throwing an exception:
> >>>             >>>
> >>>             >>> // IDXGIFactory1** dxgiFactory;
> >>>             >>> var dxgiFactory = scope.allocate(C_POINTER);
> >>>             >>> // HRESULT = CreateDXGIFactory1(_uuid(dxgiFactory),
> >>>             &dxgiFactory))
> >>>             >>> int hresult =
> >>> dxgi_h.CreateDXGIFactory1(GUID(IID.IID_IDXGIFactory1),
> >>>             >>> dxgiFactory);
> >>>             >>> System.out.println("hresult: " + hresult);
> >>>             >>> var dxgiAdapter = scope.allocate(C_POINTER);
> >>>             >>> System.out.println("IDXGIFactory1Vtbl byte size: " +
> >>>             >>> dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize()); //112
> >>>             >>> MemorySegment segment =
> >>>             >>>
> >>>
> MemorySegment.allocateNative(dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize());
> >>>
> >>>             >>>
> >>>             >>> MemoryAddress address =
> >>> segment.address().addOffset(64);
> >>>             >>> FunctionDescriptor functionDescriptor =
> >>>             FunctionDescriptor.of(C_INT,
> >>>             >>> C_INT,
> >>>             >>> C_POINTER);
> >>>             >>> MethodType methodType =
> >>>             MethodType.methodType(int.class, int.class,
> >>>             >>> MemoryAddress.class);
> >>>             >>> MethodHandle methodHandle =
> >>>             getSystemLinker().downcallHandle(address,
> >>>             >>> methodType, functionDescriptor);
> >>>             >>> try {
> >>>             >>> methodHandle.invokeWithArguments(0,
> >>>             dxgiAdapter.address());
> >>>             >>> } catch (Throwable throwable) {
> >>>             >>> throwable.printStackTrace();
> >>>             >>> }
> >>>             >>>
> >>>             >>> On Sat, Sep 12, 2020 at 6:34 PM Michael Ennen
> >>>             <mike.ennen at gmail.com <mailto:mike.ennen at gmail.com>>
> >>>             >>> wrote:
> >>>             >>>
> >>>             >>>> I think I see why. It's because I am passing in a
> >>>             MemorySegment,
> >>>             >>>> which is
> >>>             >>>> the dxgiAdapter which I initialize thusly:
> >>>             >>>>
> >>>             >>>> var dxgiAdapter = scope.allocate(C_POINTER);
> >>>             >>>>
> >>>             >>>> I guess I need to make it a MemoryAddress instead.
> >>>             >>>>
> >>>             >>>> On Sat, Sep 12, 2020 at 2:25 PM Michael Ennen
> >>>             <mike.ennen at gmail.com <mailto:mike.ennen at gmail.com>>
> >>>             >>>> wrote:
> >>>             >>>>
> >>>             >>>>> Thanks so much Ty. That's super helpful. I think I
> >>>             was able to
> >>>             >>>>> make quite
> >>>             >>>>> a bit of progress:
> >>>             >>>>>
> >>>             >>>>> var dxgiAdapter = scope.allocate(C_POINTER);
> >>>             >>>>> System.out.println("IDXGIFactory1Vtbl byte size: " +
> >>>             >>>>> dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize());
> >>>             >>>>> MemorySegment segment =
> >>>             >>>>>
> >>>
> MemorySegment.allocateNative(dxgi_h.IDXGIFactory1Vtbl.$LAYOUT().byteSize());
> >>>
> >>>             >>>>>
> >>>             >>>>> MemoryAddress address =
> >>>             segment.address().addOffset(64);
> >>>             >>>>> FunctionDescriptor functionDescriptor =
> >>>             FunctionDescriptor.of(C_INT,
> >>>             >>>>> C_INT, C_POINTER);
> >>>             >>>>> MethodType methodType =
> >>>             MethodType.methodType(int.class, int.class,
> >>>             >>>>> MemoryAddress.class);
> >>>             >>>>> MethodHandle methodHandle =
> >>>             getSystemLinker().downcallHandle(address,
> >>>             >>>>> methodType, functionDescriptor);
> >>>             >>>>> try {
> >>>             >>>>> methodHandle.invokeWithArguments(0, dxgiAdapter);
> >>>             >>>>> } catch (Throwable throwable) {
> >>>             >>>>> throwable.printStackTrace();
> >>>             >>>>> }
> >>>             >>>>>
> >>>             >>>>> Note that the EnumAdapters1 function signature is
> >>>             actually:
> >>>             >>>>>
> >>>             >>>>> HRESULT EnumAdapters1(
> >>>             >>>>>    UINT          Adapter,
> >>>             >>>>>    IDXGIAdapter1 **ppAdapter
> >>>             >>>>> );
> >>>             >>>>>
> >>>             >>>>>
> >>>             >>>>> So that's why I went with:
> >>>             >>>>>
> >>>             >>>>> FunctionDescriptor functionDescriptor =
> >>>             FunctionDescriptor.of(C_INT,
> >>>             >>>>> C_INT, C_POINTER);
> >>>             >>>>>
> >>>             >>>>> and then
> >>>             >>>>>
> >>>             >>>>> methodHandle.invokeWithArguments(0, dxgiAdapter);
> >>>             >>>>>
> >>>             >>>>> I did some fancy stuff as per your suggestion which
> >>>             I feel should be
> >>>             >>>>> getting the address of the EumAdapters1 function
> >>>             >>>>> pointer (basically start at the base address of the
> >>>             struct and
> >>>             >>>>> then move
> >>>             >>>>> 64 bytes past, which should be the 8th function
> >>>             >>>>> pointer which in this case is EnumAdapters1).
> >>>             >>>>>
> >>>             >>>>> I do get the following exception on invoking the
> >>>             method handle,
> >>>             >>>>> though:
> >>>             >>>>>
> >>>             >>>>> hresult: 0
> >>>             >>>>> factory: MemorySegment{ id=0x3898fd8a limit: 8 }
> >>>             >>>>> IDXGIFactory1Vtbl byte size: 112
> >>>             >>>>> java.lang.ClassCastException: Cannot cast
> >>>             >>>>> jdk.internal.foreign.NativeMemorySegmentImpl to
> >>>             >>>>> jdk.incubator.foreign.MemoryAddress
> >>>             >>>>>          at
> >>>             java.base/java.lang.Class.cast(Class.java:3816)
> >>>             >>>>>          at
> >>>             >>>>>
> >>>
> java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733)
> >>>
> >>>             >>>>>
> >>>             >>>>>          at com.dx12.DX12.main(DX12.java:91)
> >>>             >>>>>          at
> >>>             >>>>>
> >>> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native
> >>>
> >>>             >>>>>
> >>>             >>>>> Method)
> >>>             >>>>>          at
> >>>             >>>>>
> >>>
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
> >>>
> >>>             >>>>>
> >>>             >>>>>          at
> >>>             >>>>>
> >>>
> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> >>>
> >>>             >>>>>
> >>>             >>>>>          at
> >>>             >>>>>
> >>> java.base/java.lang.reflect.Method.invoke(Method.java:564)
> >>>             >>>>>          at
> >>>             >>>>>
> >>> jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:415)
> >>>             >>>>>          at
> >>>             >>>>>
> >>> jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
> >>>             >>>>>          at
> >>>             >>>>>
> >>> jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
> >>>             >>>>> vh:
> >>> VarHandle[varType=jdk.incubator.foreign.MemoryAddress,
> >>>             >>>>> coord=[interface
> >>> jdk.incubator.foreign.MemorySegment]]
> >>>             >>>>>
> >>>             >>>>> Any more assistance would be greatly appreciate but
> >>>             undeserved :).
> >>>             >>>>>
> >>>             >>>>>
> >>>             >>>>> On Sat, Sep 12, 2020 at 1:41 AM Ty Young
> >>>             <youngty1997 at gmail.com <mailto:youngty1997 at gmail.com>>
> >>>             >>>>> wrote:
> >>>             >>>>>
> >>>             >>>>>> Not a JDK developer, but if you want to do this by
> >>>             hand(aka no
> >>>             >>>>>> jextract), I had to do this for NVAPI which
> >>>             obfuscates function
> >>>             >>>>>> pointers
> >>>             >>>>>> using keys, e.g.:
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> nvapi_h.nvapi_QueryInterface(0x0150e828);
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> where "0x0150e828" is the "NvAPI_Initialize"
> >>>             function key as per the
> >>>             >>>>>> Open Source headers Nvidia released sometime ago.
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> The only difference is that, since the function
> >>>             pointer is in a
> >>>             >>>>>> struct,
> >>>             >>>>>> you need to get the segment in the struct
> >>>             containing the function
> >>>             >>>>>> pointer(see "slice" MemorySegment method) and
> >>>             actually read from it
> >>>             >>>>>> using a VarHandle. You then take that
> >>>             MemoryAddress, with a
> >>>             >>>>>> FunctionDescriptor and MethodType, and create a
> >>>             MethodHandle. For
> >>>             >>>>>> reference, this my working code("NativeFunction" and
> >>>             >>>>>> "NativeTypes" do
> >>>             >>>>>> not exist in Panama, those are mine but they dont
> >>>             matter) for the
> >>>             >>>>>> NvAPI_Initalize API:
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> public class NvAPI_Initialize implements
> >>>             NativeFunction
> >>>             >>>>>> {
> >>>             >>>>>>       private final MemoryAddress address;
> >>>             >>>>>>       private final FunctionDescriptor descriptor;
> >>>             >>>>>>       private final MethodType type;
> >>>             >>>>>>
> >>>             >>>>>>       private final MethodHandle handle;
> >>>             >>>>>>
> >>>             >>>>>>       public NvAPI_Initialize() throws
> >>>             NoSuchMethodException,
> >>>             >>>>>> Throwable
> >>>             >>>>>>       {
> >>>             >>>>>>           this.address =
> >>>             nvapi_h.nvapi_QueryInterface(0x0150e828);
> >>>             >>>>>>
> >>>             >>>>>>           this.descriptor =
> >>>             FunctionDescriptor.of(NativeTypes.INT);
> >>>             >>>>>>
> >>>             >>>>>>           this.type =
> >>>             MethodType.methodType(int.class);
> >>>             >>>>>>
> >>>             >>>>>>           this.handle =
> >>>             >>>>>>
> >>> CSupport.getSystemLinker().downcallHandle(this.address,
> >>>             this.type,
> >>>             >>>>>> this.descriptor);
> >>>             >>>>>>       }
> >>>             >>>>>>
> >>>             >>>>>>       // etc
> >>>             >>>>>>
> >>>             >>>>>> }
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> It looks like in your case the FunctionDescriptor
> >>>             would be:
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> this.descriptor =
> >>>             FunctionDescriptor.of(CSupport.C_POINTER,
> >>>             >>>>>> CSupport.C_INT, CSupport.C_POINTER);
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> for MethodType:
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> MethodType.methodType(MemoryAddress.class,
> >>> int.class,
> >>>             >>>>>> MemoryAddress.class);
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> where the first argument takes in a IDXGIFactory,
> >>>             the second an
> >>>             >>>>>> unsigned
> >>>             >>>>>> int, and the third a pointer to what looks like an
> >>>             opaque device
> >>>             >>>>>> that
> >>>             >>>>>> you pass to other functions.
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> If you haven't already, it might help to make
> >>>             bindings with a
> >>>             >>>>>> smaller,
> >>>             >>>>>> less complicated library just to get a feel with
> >>>             how things work
> >>>             >>>>>> under
> >>>             >>>>>> the hood.
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> Hope this helps.
> >>>             >>>>>>
> >>>             >>>>>>
> >>>             >>>>>> On 9/12/20 2:23 AM, Michael Ennen wrote:
> >>>             >>>>>>> Looking into this a bit further I think I chose a
> >>>             really bad
> >>>             >>>>>>> library to
> >>>             >>>>>>> start with as the function I need to call,
> >>>             EnumAdapters, is inside
> >>>             >>>>>>> some type of "VTbl" struct that is trying to
> >>>             emulate a C++ class
> >>>             >>>>>>> with
> >>>             >>>>>>> virtual functions. What jextract is returning is
> >>>             most likely
> >>>             >>>>>>> *correct*
> >>>             >>>>>>> but in this case so complicated because of how it
> >>>             is laid out in
> >>>             >>>>>>> C. It
> >>>             >>>>>> is
> >>>             >>>>>>> not clear at all how to grab the EnumAdapters
> >>>             function from
> >>>             >>>>>>> this mess, and it is probably above my head.
> >>>             >>>>>>>
> >>>             >>>>>>> EXTERN_C const IID IID_IDXGIFactory;
> >>>             >>>>>>>
> >>>             >>>>>>> #if defined(__cplusplus) && !defined(CINTERFACE)
> >>>             >>>>>>>
> >>>             >>>>>>>
> >>> MIDL_INTERFACE("7b7166ec-21c7-44ae-b21a-c9ae321ae369")
> >>>             >>>>>>>       IDXGIFactory : public IDXGIObject
> >>>             >>>>>>>       {
> >>>             >>>>>>>       public:
> >>>             >>>>>>>           virtual HRESULT STDMETHODCALLTYPE
> >>>             EnumAdapters(
> >>>             >>>>>>>               /* [in] */ UINT Adapter,
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>> _COM_Outptr_ IDXGIAdapter **ppAdapter) = 0;
> >>>             >>>>>>>
> >>>             >>>>>>>           virtual HRESULT STDMETHODCALLTYPE
> >>>             MakeWindowAssociation(
> >>>             >>>>>>>               HWND WindowHandle,
> >>>             >>>>>>>               UINT Flags) = 0;
> >>>             >>>>>>>
> >>>             >>>>>>>           virtual HRESULT STDMETHODCALLTYPE
> >>>             GetWindowAssociation(
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>>               _Out_ HWND *pWindowHandle) = 0;
> >>>             >>>>>>>
> >>>             >>>>>>>           virtual HRESULT STDMETHODCALLTYPE
> >>>             CreateSwapChain(
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>>               _In_ IUnknown *pDevice,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>>               _In_ DXGI_SWAP_CHAIN_DESC *pDesc,
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>> _COM_Outptr_ IDXGISwapChain **ppSwapChain) = 0;
> >>>             >>>>>>>
> >>>             >>>>>>>           virtual HRESULT STDMETHODCALLTYPE
> >>>             CreateSoftwareAdapter(
> >>>             >>>>>>>               /* [in] */ HMODULE Module,
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>> _COM_Outptr_ IDXGIAdapter **ppAdapter) = 0;
> >>>             >>>>>>>
> >>>             >>>>>>>       };
> >>>             >>>>>>>
> >>>             >>>>>>>
> >>>             >>>>>>> #else /* C style interface */
> >>>             >>>>>>>
> >>>             >>>>>>>       typedef struct IDXGIFactoryVtbl
> >>>             >>>>>>>       {
> >>>             >>>>>>> BEGIN_INTERFACE
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *QueryInterface )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [in] */ REFIID riid,
> >>>             >>>>>>>               /* [annotation][iid_is][out] */
> >>>             >>>>>>> _COM_Outptr_  void **ppvObject);
> >>>             >>>>>>>
> >>>             >>>>>>>           ULONG ( STDMETHODCALLTYPE *AddRef )(
> >>>             >>>>>>> IDXGIFactory * This);
> >>>             >>>>>>>
> >>>             >>>>>>>           ULONG ( STDMETHODCALLTYPE *Release )(
> >>>             >>>>>>> IDXGIFactory * This);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *SetPrivateData )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>>               _In_ REFGUID Name,
> >>>             >>>>>>>               /* [in] */ UINT DataSize,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>> _In_reads_bytes_(DataSize)  const void *pData);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *SetPrivateDataInterface )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>>               _In_ REFGUID Name,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>> _In_opt_  const IUnknown *pUnknown);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *GetPrivateData )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>>               _In_ REFGUID Name,
> >>>             >>>>>>>               /* [annotation][out][in] */
> >>>             >>>>>>> _Inout_  UINT *pDataSize,
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>> _Out_writes_bytes_(*pDataSize)  void *pData);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE *GetParent )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>>               _In_ REFIID riid,
> >>>             >>>>>>>               /* [annotation][retval][out] */
> >>>             >>>>>>> _COM_Outptr_  void **ppParent);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *EnumAdapters )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [in] */ UINT Adapter,
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>> _COM_Outptr_ IDXGIAdapter **ppAdapter);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *MakeWindowAssociation )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               HWND WindowHandle,
> >>>             >>>>>>>               UINT Flags);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *GetWindowAssociation )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>>               _Out_ HWND *pWindowHandle);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *CreateSwapChain )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>>               _In_ IUnknown *pDevice,
> >>>             >>>>>>>               /* [annotation][in] */
> >>>             >>>>>>>               _In_ DXGI_SWAP_CHAIN_DESC *pDesc,
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>> _COM_Outptr_ IDXGISwapChain **ppSwapChain);
> >>>             >>>>>>>
> >>>             >>>>>>>           HRESULT ( STDMETHODCALLTYPE
> >>>             *CreateSoftwareAdapter )(
> >>>             >>>>>>> IDXGIFactory * This,
> >>>             >>>>>>>               /* [in] */ HMODULE Module,
> >>>             >>>>>>>               /* [annotation][out] */
> >>>             >>>>>>> _COM_Outptr_ IDXGIAdapter **ppAdapter);
> >>>             >>>>>>>
> >>>             >>>>>>> END_INTERFACE
> >>>             >>>>>>>       } IDXGIFactoryVtbl;
> >>>             >>>>>>>
> >>>             >>>>>>>       interface IDXGIFactory
> >>>             >>>>>>>       {
> >>>             >>>>>>>           CONST_VTBL struct IDXGIFactoryVtbl
> >>> *lpVtbl;
> >>>             >>>>>>>       };
> >>>             >>>>>>>
> >>>             >>>>>>>
> >>>             >>>>>
> >>>             >>>>> --
> >>>             >>>>> Michael Ennen
> >>>             >>>>>
> >>>             >>>>
> >>>             >>>> --
> >>>             >>>> Michael Ennen
> >>>             >>>>
> >>>             >>>
> >>>
> >>>
> >>>
> >>>         --         Michael Ennen
> >>>
> >>>
> >>>
> >>>     --     Michael Ennen
> >>
> >>
> >>
> >> --
> >> Michael Ennen
>


-- 
Michael Ennen


More information about the panama-dev mailing list