nukleer bomb
nukleer bomb
CC#
Created by nukleer bomb on 2/10/2023 in #help
❔ `delegate*` wrapper throws `System.BadImageFormatException`
I wrote some wrapper for delegate* unmanaged to use it in F# since it doesn't support function pointers:
using Microsoft.FSharp.Core;

public unsafe struct FuncPtr<TArg, TRet>
{
private readonly nint ptr;

public FuncPtr(nint ptr) => this.ptr = ptr;

public TRet Call(TArg arg)
{
if (typeof(TRet) == typeof(Unit))
{
if (typeof(TArg) == typeof(Unit))
((delegate* unmanaged<void>)ptr)();
else
((delegate* unmanaged<TArg, void>)ptr)(arg);

return default!;
}
else
{
return typeof(TArg) == typeof(Unit) ?
((delegate* unmanaged<TRet>)ptr)() :
((delegate* unmanaged<TArg, TRet>)ptr)(arg);
}
}
}
using Microsoft.FSharp.Core;

public unsafe struct FuncPtr<TArg, TRet>
{
private readonly nint ptr;

public FuncPtr(nint ptr) => this.ptr = ptr;

public TRet Call(TArg arg)
{
if (typeof(TRet) == typeof(Unit))
{
if (typeof(TArg) == typeof(Unit))
((delegate* unmanaged<void>)ptr)();
else
((delegate* unmanaged<TArg, void>)ptr)(arg);

return default!;
}
else
{
return typeof(TArg) == typeof(Unit) ?
((delegate* unmanaged<TRet>)ptr)() :
((delegate* unmanaged<TArg, TRet>)ptr)(arg);
}
}
}
But when I try to call Call() method:
using KiDev.IlAsm.FuncPtr;
using Microsoft.FSharp.Core;
using System.Runtime.InteropServices;

unsafe
{
delegate* unmanaged<int> x = &Test;
Console.WriteLine($"delegate* = {x()}"); // fine

var ptr = new FuncPtr<Unit, int>((nint)x);
Console.WriteLine($"FuncPtr = {ptr.Call(null!)}"); // exception
}

[UnmanagedCallersOnly]
static int Test() => 12;
using KiDev.IlAsm.FuncPtr;
using Microsoft.FSharp.Core;
using System.Runtime.InteropServices;

unsafe
{
delegate* unmanaged<int> x = &Test;
Console.WriteLine($"delegate* = {x()}"); // fine

var ptr = new FuncPtr<Unit, int>((nint)x);
Console.WriteLine($"FuncPtr = {ptr.Call(null!)}"); // exception
}

[UnmanagedCallersOnly]
static int Test() => 12;
I get System.BadImageFormatException: "Bad element type in SizeOf.". What I am doing wrong?
78 replies