Error Running jextract on d3d12.h

Michael Ennen mike.ennen at gmail.com
Mon Sep 14 23:05:17 UTC 2020


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

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


More information about the panama-dev mailing list