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(SR.Argument_NeedNonGenericObject, nameof(structure)); } 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()) { ((delegate * < ref byte, ref byte, void >)marshalStub)(ref structure.GetRawData(), ref *(byte *)ptr); } else { ((delegate * < object, ref byte, void >)marshalStub)(structure, ref *(byte *)ptr); } } else { nuint size = (nuint)RuntimeAugments.InteropCallbacks.GetStructUnsafeStructSize(structureTypeHandle); Buffer.Memmove(ref *(byte *)ptr, ref structure.GetRawData(), size); } }
private static uint SizeOf <T>() where T : struct { RuntimeTypeHandle structureTypeHandle = typeof(T).TypeHandle; if (!structureTypeHandle.IsBlittable()) { throw new ArgumentException(SR.Argument_NeedStructWithNoRefs); } return((uint)Unsafe.SizeOf <T>()); }
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) ); } }
public override int GetStructUnsafeStructSize(RuntimeTypeHandle structureTypeHandle) { if (TryGetStructUnsafeStructSize(structureTypeHandle, out int size)) { return(size); } // IsBlittable() checks whether the type contains GC references. It is approximate check with false positives. // This fallback path will return incorrect answer for types that do not contain GC references, but that are // not actually blittable; e.g. for types with bool fields. if (structureTypeHandle.IsBlittable() && structureTypeHandle.IsValueType()) { return(structureTypeHandle.GetValueTypeSize()); } throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, Type.GetTypeFromHandle(structureTypeHandle)); }
private static int SizeOf(Type t) { Debug.Assert(t != null, "t"); if (t.TypeHandle.IsGenericType()) { throw new ArgumentException(SR.Argument_NeedNonGenericType, "t"); } RuntimeTypeHandle typeHandle = t.TypeHandle; if (!(typeHandle.IsBlittable() && typeHandle.IsValueType())) { throw new ArgumentException(SR.Argument_NeedStructWithNoRefs); } return(typeHandle.GetValueTypeSize()); }
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 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, nameof(structuretype)); } 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 = RuntimeInteropData.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 destroyed if (destroyStructureStub != IntPtr.Zero) { ((delegate * < ref byte, void >)destroyStructureStub)(ref *(byte *)ptr); } }
internal static void GenericStructureToPtr <T>(ref T structure, byte *ptr, uint sizeofT) where T : struct { RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle; if (!structureTypeHandle.IsBlittable()) { throw new ArgumentException(SR.Argument_NeedStructWithNoRefs); } InteropExtensions.PinObjectAndCall((Object)structure, unboxedStructPtr => { InteropExtensions.Memcpy( (IntPtr)ptr, // unsafe (no need to adjust as it is always struct) (IntPtr)((IntPtr *)unboxedStructPtr + 1), // safe (need to adjust offset as boxed structure start at offset 1) (int)sizeofT ); }); }
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 nuint offset = structureTypeHandle.IsValueType() ? (nuint)sizeof(IntPtr) : 0; IntPtr unmarshalStub; if (structureTypeHandle.IsBlittable()) { if (!RuntimeAugments.InteropCallbacks.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub)) { unmarshalStub = IntPtr.Zero; } } else { unmarshalStub = RuntimeAugments.InteropCallbacks.GetStructUnmarshalStub(structureTypeHandle); } ref byte dest = ref Unsafe.AddByteOffset(ref Unsafe.As<IntPtr, byte>(ref structure.m_pEEType), offset);
internal static void GenericPtrToStructure <T>(byte *ptr, out T structure, uint sizeofT) where T : struct { RuntimeTypeHandle structureTypeHandle = typeof(T).TypeHandle; if (!structureTypeHandle.IsBlittable()) { throw new ArgumentException(SR.Argument_NeedStructWithNoRefs); } Object boxedStruct = new T(); InteropExtensions.PinObjectAndCall(boxedStruct, unboxedStructPtr => { InteropExtensions.Memcpy( (IntPtr)((IntPtr *)unboxedStructPtr + 1), // safe (need to adjust offset as boxed structure start at offset 1) (IntPtr)ptr, // unsafe (no need to adjust as it is always struct) (int)sizeofT ); }); structure = (T)boxedStruct; }
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()) { ((delegate * < ref byte, ref byte, void >)unmarshalStub)(ref *(byte *)ptr, ref structure.GetRawData()); } else { ((delegate * < ref byte, object, void >)unmarshalStub)(ref *(byte *)ptr, structure); } } else { nuint size = (nuint)RuntimeAugments.InteropCallbacks.GetStructUnsafeStructSize(structureTypeHandle); Buffer.Memmove(ref structure.GetRawData(), ref *(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); } // 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 ); }); } }