Skip to content

Commit

Permalink
Merge pull request #8 from ilyfairy/preview
Browse files Browse the repository at this point in the history
Preview
  • Loading branch information
ilyfairy authored Dec 31, 2022
2 parents 6e6fca6 + 7d87eed commit dcc9756
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 50 deletions.
7 changes: 7 additions & 0 deletions UnsafeHelper.IL/IL.il
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@
ldarg.0
ret
}

.method public hidebysig static !!T As<class T>(void* objectAddress) cil managed aggressiveinlining
{
.maxstack 2
ldarg.0
ret
}
}
44 changes: 44 additions & 0 deletions UnsafeHelper/ManagedObject.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using IlyfairyLib.Unsafe.Internal;
using System;
using System.Runtime.InteropServices;

namespace IlyfairyLib.Unsafe;

/// <summary>
/// 自动回收的托管对象
/// </summary>
/// <typeparam name="T"></typeparam>
public unsafe class ManagedObject<T> where T : class
{
/// <summary>
/// 前(nint)字节为TypeHandle
/// </summary>
private readonly byte[] data;
public int Size => data.Length;
public nint* Handle => (nint*)(UnsafeHelper.GetObjectRawDataAddress(data) + 8);
public T Object { get; private set; }
private readonly GCHandle gcHandle;
private ManagedObject(byte[] data, object obj)
{
Object = System.Runtime.CompilerServices.Unsafe.As<T>(obj);
this.data = data;
}
public ManagedObject(int size)
{
if (size <= 8) size = 8;
size += 8;
data = new byte[size];
var handle = Handle;
*handle = typeof(T).TypeHandle.Value;
Object = IL.As<T>(handle);
gcHandle = GCHandle.Alloc(Object);
}
~ManagedObject()
{
gcHandle.Free();
}
public Span<T> GetDataSpan<T>() where T : unmanaged => new((byte*)Handle + sizeof(nint), Size / sizeof(T));
public void ChangeType(Type type) => *Handle = type.TypeHandle.Value;
public void ChangeType<T>() => *Handle = typeof(T).TypeHandle.Value;
public ManagedObject<TTo> As<TTo>() where TTo : class => System.Runtime.CompilerServices.Unsafe.As<ManagedObject<TTo>>(this);
}
34 changes: 34 additions & 0 deletions UnsafeHelper/StructExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IlyfairyLib.Unsafe;

public static class StructExtension
{
public static unsafe TStruct ToStruct<TStruct>(this byte[] bytes) where TStruct : struct
{
if (sizeof(TStruct) != bytes.Length)
throw new ArgumentOutOfRangeException(nameof(bytes), "Bytes array should be the same length as struct size.");
TStruct val;
fixed (byte* p = bytes)
{
Buffer.MemoryCopy(p, &val, (ulong)sizeof(TStruct), (ulong)sizeof(TStruct));
return val;
}
}

public static unsafe TStruct ToStruct<TStruct>(this Span<byte> bytes) where TStruct : struct
{
if (sizeof(TStruct) != bytes.Length)
throw new ArgumentOutOfRangeException(nameof(bytes), "Bytes array should be the same length as struct size.");
TStruct val;
fixed (byte* p = bytes)
{
Buffer.MemoryCopy(p, &val, (ulong)sizeof(TStruct), (ulong)sizeof(TStruct));
return val;
}
}
}
Loading

0 comments on commit dcc9756

Please sign in to comment.