hacks: add NetVips hacks to minimize string allocation
This commit is contained in:
parent
3307c56221
commit
7c637eec3e
2 changed files with 72 additions and 0 deletions
38
src/Oh.My.Stitcher/NetVips/GObjectHacks.cs
Normal file
38
src/Oh.My.Stitcher/NetVips/GObjectHacks.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security;
|
||||||
|
using NetVips.Internal;
|
||||||
|
using GObjectManaged = NetVips.GObject;
|
||||||
|
|
||||||
|
namespace Oh.My.Stitcher.NetVips;
|
||||||
|
|
||||||
|
|
||||||
|
internal static unsafe class GObjectHacks
|
||||||
|
{
|
||||||
|
internal static void SetProperty(GObjectManaged gObject, string name, ReadOnlySpan<byte> value)
|
||||||
|
{
|
||||||
|
var gvStruct = new GValue.Struct();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
GValue.Init(ref gvStruct, 16 << 2);
|
||||||
|
fixed( byte* pValue = value )
|
||||||
|
{
|
||||||
|
GValueHacks.SetString(ref gvStruct, pValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
GObject.SetProperty(gObject, name, in gvStruct);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
GValue.Unset(ref gvStruct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static unsafe class GValueHacks
|
||||||
|
{
|
||||||
|
[SuppressUnmanagedCodeSecurity]
|
||||||
|
[DllImport("libgobject-2.0.so.0", CallingConvention = CallingConvention.Cdecl,
|
||||||
|
EntryPoint = "g_value_set_string")]
|
||||||
|
internal static extern void SetString(ref GValue.Struct value, byte* vString);
|
||||||
|
}
|
||||||
34
src/Oh.My.Stitcher/NetVips/OperationHacks.cs
Normal file
34
src/Oh.My.Stitcher/NetVips/OperationHacks.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
using NetVips;
|
||||||
|
using NetVips.Internal;
|
||||||
|
using VipsObject = NetVips.Internal.VipsObject;
|
||||||
|
|
||||||
|
namespace Oh.My.Stitcher.NetVips;
|
||||||
|
|
||||||
|
public static class OperationHacks
|
||||||
|
{
|
||||||
|
public static object Call(string operationName, ReadOnlySpan<byte> arg)
|
||||||
|
{
|
||||||
|
var intro = Introspect.Get(operationName);
|
||||||
|
if (intro.RequiredInput.Count != 1)
|
||||||
|
throw new ArgumentException($"unable to call {operationName}");
|
||||||
|
|
||||||
|
nint vop;
|
||||||
|
using( var op = Operation.NewFromName(operationName) )
|
||||||
|
{
|
||||||
|
Introspect.Argument requiredArg = intro.RequiredInput[0];
|
||||||
|
GObjectHacks.SetProperty(op, requiredArg.Name, arg);
|
||||||
|
vop = VipsOperation.Build(op);
|
||||||
|
if (vop == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
VipsObject.UnrefOutputs(op);
|
||||||
|
throw new VipsException($"unable to call {operationName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var op = new Operation(vop))
|
||||||
|
{
|
||||||
|
object? result = op.Get(intro.RequiredOutput[0].Name);
|
||||||
|
VipsObject.UnrefOutputs(op);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue