private T ReadInternal<T>(IntPtr address) where T : struct { var type = MarshalCache<T>.RealType; if (!MarshalCache<T>.TypeRequiresMarshal) { var val = default(T); // If the (value) type doesn't require marshalling, we can simply use MoveMemory to move the entire // thing in one swoop. This is significantly faster than having it go through the Marshal. var ptr = MarshalCache<T>.GetUnsafePtr(ref val); MoveMemory(ptr, (void*) address, MarshalCache<T>.Size); return val; } // Have the marshal deal with it for now. return Marshal.PtrToStructure<T>(address); // Scrapped until it can be properly unit tested. //object ret = null; //var typeCode = Type.GetTypeCode(type); //// Special case simple value types: //// - Boolean //// - Byte, SByte //// - Char //// - Decimal //// - Int32, UInt32 //// - Int64, UInt64 //// - Int16, UInt16 //// - IntPtr, UIntPtr //// As of .NET 4.5, the (Type)(object)result pattern used below //// is recognized and optimized by both 32-bit and 64-bit JITs. //// Therefore, do not change this to a switch - JIT won't apply same optimization (it won't box!). //if (typeCode == TypeCode.Boolean) // ret = *(byte*)address != 0; //if (typeCode == TypeCode.Byte) // ret = *(byte*)address; //if (typeCode == TypeCode.SByte) // ret = *(sbyte*)address; //if (typeCode == TypeCode.Char) // ret = *(char*)address; //if (typeCode == TypeCode.Decimal) // ret = *(decimal*)address; //if (typeCode == TypeCode.Int32) // ret = *(int*)address; //if (typeCode == TypeCode.UInt32) // ret = *(uint*)address; //if (typeCode == TypeCode.Int64) // ret = *(long*)address; //if (typeCode == TypeCode.UInt64) // ret = *(ulong*)address; //if (typeCode == TypeCode.Int16) // ret = *(short*)address; //if (typeCode == TypeCode.UInt16) // ret = *(ushort*)address; //return (T)ret; }
public static unsafe T Read <T>(this IntPtr address) { try { if (address == IntPtr.Zero) { throw new InvalidOperationException("Cannot retrieve a value at address 0"); } object ptrToStructure; switch (MarshalCache <T> .TypeCode) { case TypeCode.Object: if (MarshalCache <T> .RealType == typeof(IntPtr)) { return((T)(object)*(IntPtr *)address); } if (!MarshalCache <T> .TypeRequiresMarshal) { T obj = default(T); void *ptr = MarshalCache <T> .GetUnsafePtr(ref obj); Kernel32.MoveMemory(ptr, (void *)address, MarshalCache <T> .Size); return(obj); } ptrToStructure = Marshal.PtrToStructure(address, typeof(T)); break; case TypeCode.Boolean: ptrToStructure = *(byte *)address != 0; break; case TypeCode.Char: ptrToStructure = *(char *)address; break; case TypeCode.SByte: ptrToStructure = *(sbyte *)address; break; case TypeCode.Byte: ptrToStructure = *(byte *)address; break; case TypeCode.Int16: ptrToStructure = *(short *)address; break; case TypeCode.UInt16: ptrToStructure = *(ushort *)address; break; case TypeCode.Int32: ptrToStructure = *(int *)address; break; case TypeCode.UInt32: ptrToStructure = *(uint *)address; break; case TypeCode.Int64: ptrToStructure = *(long *)address; break; case TypeCode.UInt64: ptrToStructure = *(ulong *)address; break; case TypeCode.Single: ptrToStructure = *(float *)address; break; case TypeCode.Double: ptrToStructure = *(double *)address; break; default: throw new ArgumentOutOfRangeException(); } return((T)ptrToStructure); } catch (AccessViolationException) { return(default(T)); } }
private T ReadInternal <T>(IntPtr address) where T : struct { var type = MarshalCache <T> .RealType; if (!MarshalCache <T> .TypeRequiresMarshal) { var val = default(T); // If the (value) type doesn't require marshalling, we can simply use MoveMemory to move the entire // thing in one swoop. This is significantly faster than having it go through the Marshal. var ptr = MarshalCache <T> .GetUnsafePtr(ref val); MoveMemory(ptr, (void *)address, MarshalCache <T> .Size); return(val); } return(Marshal.PtrToStructure <T>(address)); }
public static unsafe T Read <T>(this IntPtr address) { try { // It may be worth it to simply use memcpy to avoid it, but I doubt thats going to give any noticeable increase in speed. if (address == IntPtr.Zero) { throw new InvalidOperationException("Cannot retrieve a value at address 0"); } object ptrToStructure; // ReSharper disable once SwitchStatementMissingSomeCases switch (MarshalCache <T> .TypeCode) { case TypeCode.Object: if (MarshalCache <T> .RealType == typeof(IntPtr)) { return((T)(object)*(IntPtr *)address); } // If the type doesn't require an explicit Marshal call, then ignore it and memcpy the thing. if (!MarshalCache <T> .TypeRequiresMarshal) { var o = default(T); var ptr = MarshalCache <T> .GetUnsafePtr(ref o); Kernel32.MoveMemory(ptr, (void *)address, MarshalCache <T> .Size); return(o); } // All System.Object's require marshaling! ptrToStructure = Marshal.PtrToStructure(address, typeof(T)); break; case TypeCode.Boolean: ptrToStructure = *(byte *)address != 0; break; case TypeCode.Char: ptrToStructure = *(char *)address; break; case TypeCode.SByte: ptrToStructure = *(sbyte *)address; break; case TypeCode.Byte: ptrToStructure = *(byte *)address; break; case TypeCode.Int16: ptrToStructure = *(short *)address; break; case TypeCode.UInt16: ptrToStructure = *(ushort *)address; break; case TypeCode.Int32: ptrToStructure = *(int *)address; break; case TypeCode.UInt32: ptrToStructure = *(uint *)address; break; case TypeCode.Int64: ptrToStructure = *(long *)address; break; case TypeCode.UInt64: ptrToStructure = *(ulong *)address; break; case TypeCode.Single: ptrToStructure = *(float *)address; break; case TypeCode.Double: ptrToStructure = *(double *)address; break; case TypeCode.Decimal: // Probably safe to remove this. I'm unaware of anything that actually uses "decimal" that would require memory reading... ptrToStructure = *(decimal *)address; break; default: throw new ArgumentOutOfRangeException(); } return((T)ptrToStructure); } catch (AccessViolationException ex) { Trace.WriteLine("Access Violation on " + address + " with type " + typeof(T).Name + Environment.NewLine + ex); return(default);
private T InternalRead <T>(IntPtr address) where T : struct { try { if (address == IntPtr.Zero) { throw new InvalidOperationException("Cannot retrieve a value at address 0"); } object returnValue; switch (MarshalCache <T> .TypeCode) { case TypeCode.Object: if (MarshalCache <T> .RealType == typeof(IntPtr)) { return((T)(object)*(IntPtr *)address); } if (!MarshalCache <T> .TypeRequiresMarshal) { T o = default(T); void *ptr = MarshalCache <T> .GetUnsafePtr(ref o); NativeMethods.MoveMemory(ptr, (void *)address, MarshalCache <T> .Size); return(o); } // All System.Object's require marshaling! returnValue = Marshal.PtrToStructure(address, typeof(T)); break; case TypeCode.SByte: returnValue = *(sbyte *)address; break; case TypeCode.Byte: returnValue = *(byte *)address; break; case TypeCode.Int16: returnValue = *(short *)address; break; case TypeCode.UInt16: returnValue = *(ushort *)address; break; case TypeCode.Int32: returnValue = *(int *)address; break; case TypeCode.UInt32: returnValue = *(uint *)address; break; case TypeCode.Int64: returnValue = *(long *)address; break; case TypeCode.UInt64: returnValue = *(ulong *)address; break; case TypeCode.Single: returnValue = *(float *)address; break; case TypeCode.Double: returnValue = *(double *)address; break; case TypeCode.Decimal: returnValue = *(decimal *)address; break; case TypeCode.Boolean: returnValue = *(byte *)address != 0; break; case TypeCode.Char: returnValue = *(char *)address; break; default: throw new ArgumentOutOfRangeException(); } return((T)returnValue); } catch (AccessViolationException) { return(default(T)); } }