Added C# binding for SKData.Create without copy
This commit is contained in:
Родитель
69130e70b5
Коммит
5905fac6d9
|
@ -14,10 +14,26 @@ using System.Text;
|
|||
|
||||
namespace SkiaSharp
|
||||
{
|
||||
// public delegates
|
||||
public delegate void SKDataReleaseDelegate (IntPtr address, object context);
|
||||
|
||||
// internal proxy delegates
|
||||
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
|
||||
internal delegate void SKDataReleaseDelegateInternal (IntPtr address, IntPtr context);
|
||||
|
||||
public class SKData : SKObject
|
||||
{
|
||||
private const int CopyBufferSize = 8192;
|
||||
|
||||
// so the GC doesn't collect the delegate
|
||||
private static readonly SKDataReleaseDelegateInternal releaseDelegateInternal;
|
||||
private static readonly IntPtr releaseDelegate;
|
||||
static SKData ()
|
||||
{
|
||||
releaseDelegateInternal = new SKDataReleaseDelegateInternal (ReleaseInternal);
|
||||
releaseDelegate = Marshal.GetFunctionPointerForDelegate (releaseDelegateInternal);
|
||||
}
|
||||
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (Handle != IntPtr.Zero && OwnsHandle) {
|
||||
|
@ -65,6 +81,26 @@ namespace SkiaSharp
|
|||
}
|
||||
}
|
||||
|
||||
public static SKData Create (IntPtr address, int length)
|
||||
{
|
||||
return Create (address, length, null, null);
|
||||
}
|
||||
|
||||
public static SKData Create (IntPtr address, int length, SKDataReleaseDelegate releaseProc)
|
||||
{
|
||||
return Create (address, length, releaseProc, null);
|
||||
}
|
||||
|
||||
public static SKData Create (IntPtr address, int length, SKDataReleaseDelegate releaseProc, object context)
|
||||
{
|
||||
if (releaseProc == null) {
|
||||
return GetObject<SKData> (SkiaApi.sk_data_new_with_proc (address, (IntPtr) length, IntPtr.Zero, IntPtr.Zero));
|
||||
} else {
|
||||
var ctx = new NativeDelegateContext (context, releaseProc);
|
||||
return GetObject<SKData> (SkiaApi.sk_data_new_with_proc (address, (IntPtr) length, releaseDelegate, ctx.NativeContext));
|
||||
}
|
||||
}
|
||||
|
||||
public static SKData FromMallocMemory (IntPtr bytes, ulong length)
|
||||
{
|
||||
if (SizeOf <IntPtr> () == 4 && length > UInt32.MaxValue)
|
||||
|
@ -135,6 +171,17 @@ namespace SkiaSharp
|
|||
}
|
||||
}
|
||||
|
||||
// internal proxy
|
||||
#if __IOS__
|
||||
[ObjCRuntime.MonoPInvokeCallback (typeof (SKDataReleaseDelegateInternal))]
|
||||
#endif
|
||||
private static void ReleaseInternal (IntPtr address, IntPtr context)
|
||||
{
|
||||
using (var ctx = NativeDelegateContext.Unwrap (context)) {
|
||||
ctx.GetDelegate<SKDataReleaseDelegate> () (address, ctx.ManagedContext);
|
||||
}
|
||||
}
|
||||
|
||||
private class SKDataStream : UnmanagedMemoryStream
|
||||
{
|
||||
private SKData host;
|
||||
|
|
|
@ -810,6 +810,9 @@ namespace SkiaSharp
|
|||
public extern static sk_data_t sk_data_new_from_file(string path);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static sk_data_t sk_data_new_from_stream(sk_stream_t stream, IntPtr length);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static sk_data_t sk_data_new_with_proc(IntPtr ptr, IntPtr length, IntPtr proc, IntPtr ctx);
|
||||
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static void sk_data_unref(sk_data_t d);
|
||||
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 379184f0ab1dfc9f2364043b70c5f65b9a3bc084
|
||||
Subproject commit 009e372b71021c6bbe5a05ec96843b2c2d554507
|
|
@ -17,6 +17,27 @@ namespace SkiaSharp.Tests
|
|||
Assert.AreEqual(OddData, data.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReleaseDataWasInvoked()
|
||||
{
|
||||
bool released = false;
|
||||
|
||||
var onRelease = new SKDataReleaseDelegate((addr, ctx) => {
|
||||
Marshal.FreeCoTaskMem(addr);
|
||||
released = true;
|
||||
Assert.AreEqual("RELEASING!", ctx);
|
||||
});
|
||||
|
||||
var memory = Marshal.AllocCoTaskMem(10);
|
||||
|
||||
using (var data = SKData.Create(memory, 10, onRelease, "RELEASING!")) {
|
||||
Assert.AreEqual(memory, data.Data);
|
||||
Assert.AreEqual(10, data.Size);
|
||||
}
|
||||
|
||||
Assert.True(released, "The SKDataReleaseDelegate was not called.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Doesn't work as it relies on memory being overwritten by an external process.")]
|
||||
public void DataDisposedReturnsInvalidStream()
|
||||
|
|
Загрузка…
Ссылка в новой задаче