hacks: add NetVips hacks to minimize string allocation

This commit is contained in:
Renjaya Raga Zenta 2025-07-31 00:26:58 +07:00
parent 3307c56221
commit 7c637eec3e
2 changed files with 72 additions and 0 deletions

View 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);
}

View 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;
}
}
}