private static __ComObject CreateComObjectInternal(RuntimeTypeHandle classType, IntPtr pComItf) { Debug.Assert(!classType.IsNull()); if (classType.Equals(McgModule.s_DependencyReductionTypeRemovedTypeHandle)) { // We should filter out the strongly typed RCW in TryGetClassInfoFromName step #if !RHTESTCL Environment.FailFast(McgTypeHelpers.GetDiagnosticMessageForMissingType(classType)); #else Environment.FailFast("We should never see strongly typed RCW discarded here"); #endif } //Note that this doesn't run the constructor in RH but probably do in your reflection based implementation. //If this were a real RCW, you would actually 'new' the RCW which is wrong. Fortunately in CoreCLR we don't have //this scenario so we are OK, but we should figure out a way to fix this by having a runtime API. object newClass = InteropExtensions.RuntimeNewObject(classType); Debug.Assert(newClass is __ComObject); __ComObject newObj = InteropExtensions.UncheckedCast <__ComObject>(newClass); IntPtr pfnCtor = AddrOfIntrinsics.AddrOf <AddrOfIntrinsics.AddrOfAttachingCtor>(__ComObject.AttachingCtor); CalliIntrinsics.Call <int>(pfnCtor, newObj, pComItf, classType); return(newObj); }
/// <summary> /// Retrieve the corresponding P/invoke instance from the stub /// </summary> public static Delegate GetPInvokeDelegateForStub(IntPtr pStub, RuntimeTypeHandle delegateType) { if (pStub == IntPtr.Zero) { return(null); } // // First try to see if this is one of the thunks we've allocated when we marshal a managed // delegate to native code // s_thunkPoolHeap will be null if there isn't any managed delegate to native // IntPtr pContext; IntPtr pTarget; if (s_thunkPoolHeap != null && RuntimeAugments.TryGetThunkData(s_thunkPoolHeap, pStub, out pContext, out pTarget)) { GCHandle handle; unsafe { // Pull out Handle from context handle = ((ThunkContextData *)pContext)->Handle; } Delegate target = InteropExtensions.UncheckedCast <Delegate>(handle.Target); // // The delegate might already been garbage collected // User should use GC.KeepAlive or whatever ways necessary to keep the delegate alive // until they are done with the native function pointer // if (target == null) { Environment.FailFast(SR.Delegate_GarbageCollected); } return(target); } // // Otherwise, the stub must be a pure native function pointer // We need to create the delegate that points to the invoke method of a // NativeFunctionPointerWrapper derived class // McgPInvokeDelegateData pInvokeDelegateData; if (!RuntimeAugments.InteropCallbacks.TryGetMarshallerDataForDelegate(delegateType, out pInvokeDelegateData)) { return(null); } return(CalliIntrinsics.Call <Delegate>( pInvokeDelegateData.ForwardDelegateCreationStub, pStub )); }
internal static unsafe void PtrToStructureImpl(IntPtr ptr, object structure) { RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle; // Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0 int offset = structureTypeHandle.IsValueType() ? 1 : 0; IntPtr unmarshalStub; if (structureTypeHandle.IsBlittable()) { if (!RuntimeAugments.InteropCallbacks.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub)) { unmarshalStub = IntPtr.Zero; } } else { unmarshalStub = RuntimeAugments.InteropCallbacks.GetStructUnmarshalStub(structureTypeHandle); } if (unmarshalStub != IntPtr.Zero) { InteropExtensions.PinObjectAndCall(structure, unboxedStructPtr => { CalliIntrinsics.Call <int>( unmarshalStub, (void *)ptr, // unsafe (no need to adjust as it is always struct) ((void *)((IntPtr *)unboxedStructPtr + offset)) // safe (need to adjust offset as it could be class) ); }); } else { int structSize = Marshal.SizeOf(structure); InteropExtensions.PinObjectAndCall(structure, unboxedStructPtr => { InteropExtensions.Memcpy( (IntPtr)((IntPtr *)unboxedStructPtr + offset), // safe (need to adjust offset as it could be class) ptr, // unsafe (no need to adjust as it is always struct) structSize ); }); } }
public static unsafe void DestroyStructure(IntPtr ptr, Type structuretype) { if (ptr == IntPtr.Zero) { throw new ArgumentNullException(nameof(ptr)); } if (structuretype == null) { throw new ArgumentNullException(nameof(structuretype)); } RuntimeTypeHandle structureTypeHandle = structuretype.TypeHandle; if (structureTypeHandle.IsGenericType() || structureTypeHandle.IsGenericTypeDefinition()) { throw new ArgumentException(SR.Argument_NeedNonGenericType, "t"); } if (structureTypeHandle.IsEnum() || structureTypeHandle.IsInterface() || InteropExtensions.AreTypesAssignable(typeof(Delegate).TypeHandle, structureTypeHandle)) { throw new ArgumentException(SR.Format(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.LastResortToString)); } if (structureTypeHandle.IsBlittable()) { // ok to call with blittable structure, but no work to do in this case. return; } IntPtr destroyStructureStub = RuntimeAugments.InteropCallbacks.GetDestroyStructureStub(structureTypeHandle, out bool hasInvalidLayout); if (hasInvalidLayout) { throw new ArgumentException(SR.Format(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.LastResortToString)); } // DestroyStructureStub == IntPtr.Zero means its fields don't need to be destroied if (destroyStructureStub != IntPtr.Zero) { CalliIntrinsics.Call <int>( destroyStructureStub, (void *)ptr // unsafe (no need to adjust as it is always struct) ); } }
internal static unsafe void PtrToStructureImpl(IntPtr ptr, object structure) { RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle; IntPtr unmarshalStub; if (structureTypeHandle.IsBlittable()) { if (!RuntimeAugments.InteropCallbacks.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub)) { unmarshalStub = IntPtr.Zero; } } else { unmarshalStub = RuntimeAugments.InteropCallbacks.GetStructUnmarshalStub(structureTypeHandle); } if (unmarshalStub != IntPtr.Zero) { if (structureTypeHandle.IsValueType()) { CalliIntrinsics.Call( unmarshalStub, ref *(byte *)ptr, ref structure.GetRawData()); } else { CalliIntrinsics.Call( unmarshalStub, ref *(byte *)ptr, structure); } } else { nuint size = (nuint)RuntimeAugments.InteropCallbacks.GetStructUnsafeStructSize(structureTypeHandle); fixed(byte *pDest = &structure.GetRawData()) { Buffer.Memmove(pDest, (byte *)ptr, size); } } }
public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld) { if (structure == null) { throw new ArgumentNullException(nameof(structure)); } if (ptr == IntPtr.Zero) { throw new ArgumentNullException(nameof(ptr)); } if (fDeleteOld) { DestroyStructure(ptr, structure.GetType()); } RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle; if (structureTypeHandle.IsGenericType() || structureTypeHandle.IsGenericTypeDefinition()) { throw new ArgumentException(nameof(structure), SR.Argument_NeedNonGenericObject); } IntPtr marshalStub; if (structureTypeHandle.IsBlittable()) { if (!RuntimeAugments.InteropCallbacks.TryGetStructMarshalStub(structureTypeHandle, out marshalStub)) { marshalStub = IntPtr.Zero; } } else { marshalStub = RuntimeAugments.InteropCallbacks.GetStructMarshalStub(structureTypeHandle); } if (marshalStub != IntPtr.Zero) { if (structureTypeHandle.IsValueType()) { CalliIntrinsics.Call(marshalStub, ref structure.GetRawData(), ref *(byte *)ptr); } else { CalliIntrinsics.Call(marshalStub, structure, ref *(byte *)ptr); } } else { nuint size = (nuint)RuntimeAugments.InteropCallbacks.GetStructUnsafeStructSize(structureTypeHandle); fixed(byte *pSrc = &structure.GetRawData()) { Buffer.Memmove((byte *)ptr, pSrc, size); } } }
public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld) { if (structure == null) { throw new ArgumentNullException(nameof(structure)); } if (ptr == IntPtr.Zero) { throw new ArgumentNullException(nameof(ptr)); } if (fDeleteOld) { DestroyStructure(ptr, structure.GetType()); } RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle; if (structureTypeHandle.IsGenericType() || structureTypeHandle.IsGenericTypeDefinition()) { throw new ArgumentException(nameof(structure), SR.Argument_NeedNonGenericObject); } // Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0 int offset = structureTypeHandle.IsValueType() ? 1 : 0; IntPtr marshalStub; if (structureTypeHandle.IsBlittable()) { if (!RuntimeAugments.InteropCallbacks.TryGetStructMarshalStub(structureTypeHandle, out marshalStub)) { marshalStub = IntPtr.Zero; } } else { marshalStub = RuntimeAugments.InteropCallbacks.GetStructMarshalStub(structureTypeHandle); } if (marshalStub != IntPtr.Zero) { InteropExtensions.PinObjectAndCall(structure, unboxedStructPtr => { CalliIntrinsics.Call <int>( marshalStub, ((void *)((IntPtr *)unboxedStructPtr + offset)), // safe (need to adjust offset as it could be class) (void *)ptr // unsafe (no need to adjust as it is always struct) ); }); } else { int structSize = Marshal.SizeOf(structure); InteropExtensions.PinObjectAndCall(structure, unboxedStructPtr => { InteropExtensions.Memcpy( ptr, // unsafe (no need to adjust as it is always struct) (IntPtr)((IntPtr *)unboxedStructPtr + offset), // safe (need to adjust offset as it could be class) structSize ); }); } }