You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Custom Marshallers never use stateful GetPinnableReference on struct #90621
@jtschuster can you share the case where this occurs? I could have sworn that we have tests that validate this behavior in the LibraryImportGenerator.Tests test suite.
In IStatefulPinnedMarshalling, with a stateless GetPinnableReference on the marshaller, the by value parameter RCW looks like this:
voidglobal::SharedTypes.ComInterfaces.IStatefulPinnedMarshalling.Method(global::SharedTypes.ComInterfaces.StatefulPinnedTypeparam){var(__this,__vtable_native)=((System.Runtime.InteropServices.Marshalling.IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(typeof(global::SharedTypes.ComInterfaces.IStatefulPinnedMarshalling));int__invokeRetVal;// Pin - Pin data in preparation for calling the P/Invoke.
fixed (void*__param_native=&global::SharedTypes.ComInterfaces.StatefulPinnedTypeMarshaller.GetPinnableReference(param)){__invokeRetVal=((delegate* unmanaged[MemberFunction]<void*,nint,int>)__vtable_native[3])(__this,(nint)__param_native);}// NotifyForSuccessfulInvoke - Keep alive any managed objects that need to stay alive across the call.System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(__invokeRetVal);System.GC.KeepAlive(this);}
With only a stateful GetPinnableReference, it looks like this:
voidglobal::SharedTypes.ComInterfaces.IStatefulPinnedMarshalling.Method(global::SharedTypes.ComInterfaces.StatefulPinnedTypeparam){var(__this,__vtable_native)=((System.Runtime.InteropServices.Marshalling.IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(typeof(global::SharedTypes.ComInterfaces.IStatefulPinnedMarshalling));nint__param_native=default;int__invokeRetVal=default;// Setup - Perform required setup.global::SharedTypes.ComInterfaces.StatefulPinnedTypeMarshaller__param_native__marshaller=new();try{// Marshal - Convert managed data to native data.__param_native__marshaller.FromManaged(param);// Pin - Pin data in preparation for calling the P/Invoke.
fixed (void*__param_native__unused=__param_native__marshaller){// PinnedMarshal - Convert managed data to native data that requires the managed data to be pinned.__param_native=__param_native__marshaller.ToUnmanaged();__invokeRetVal=((delegate* unmanaged[MemberFunction]<void*,nint,int>)__vtable_native[3])(__this,__param_native);}// NotifyForSuccessfulInvoke - Keep alive any managed objects that need to stay alive across the call.System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(__invokeRetVal);__param_native__marshaller.OnInvoked();System.GC.KeepAlive(this);}finally{// CleanupCallerAllocated - Perform cleanup of caller allocated resources.__param_native__marshaller.Free();}}
No, that is calling GetPinnableReference. The GetPinnableReference call is part of the fixed (void* __param_native__unused = __param_native__marshaller) statement (it's implied by the C# language).
Activity
jkoritzinsky commentedon Aug 15, 2023
@jtschuster can you share the case where this occurs? I could have sworn that we have tests that validate this behavior in the LibraryImportGenerator.Tests test suite.
jtschuster commentedon Aug 15, 2023
In IStatefulPinnedMarshalling, with a stateless GetPinnableReference on the marshaller, the by value parameter RCW looks like this:
With only a stateful GetPinnableReference, it looks like this:
jtschuster commentedon Aug 15, 2023
Looks like this test is supposed to, but it doesn't actually validate that GetPinnableReference was called.
jkoritzinsky commentedon Aug 16, 2023
No, that is calling
GetPinnableReference. TheGetPinnableReferencecall is part of thefixed (void* __param_native__unused = __param_native__marshaller)statement (it's implied by the C# language).