Error Running jextract on d3d12.h

Michael Ennen mike.ennen at gmail.com
Sun Sep 13 01:34:44 UTC 2020


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


More information about the panama-dev mailing list