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 ); }); } }
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 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; }
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 ); }); } }