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