-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from ilyfairy/preview
Preview
- Loading branch information
Showing
5 changed files
with
131 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
Oops, something went wrong.