C
C#3w ago
akeit0

How to get the direct function pointer of virtual struct method?

How to Get the Function Pointer of FooStruct.Foo? I have the following C# code:
interface IFoo
{
void Foo();
}

struct FooStruct : IFoo
{
public void Foo() { }
}
interface IFoo
{
void Foo();
}

struct FooStruct : IFoo
{
public void Foo() { }
}
To obtain the function pointer of FooStruct.Foo, I used:
var fp = typeof(FooStruct).GetMethod("Foo").MethodHandle.GetFunctionPointer();
var fp = typeof(FooStruct).GetMethod("Foo").MethodHandle.GetFunctionPointer();
However, fp does not point to the actual method implementation I need. Instead, it refers to the function pointer for the boxed version of FooStruct. For reference, the generated assembly is this:
L0000: add rcx, 8
L0004: mov rax, TargetFunctionPointer
L000e: jmp rax
L0000: add rcx, 8
L0004: mov rax, TargetFunctionPointer
L000e: jmp rax
I can retrieve TargetFunctionPointer by analyzing the JIT-compiled native code, but I’m looking for a more direct or reliable approach. Is there a better way to get the actual function pointer of FooStruct.Foo?
8 Replies
Unknown User
Unknown User3w ago
Message Not Public
Sign In & Join Server To View
hamarb123
hamarb1233w ago
the easiest option would be to just make a wrapper method like so:
static void Helper(ref FooStruct instance) => instance.Foo();
delegate* managed<ref FooStruct, void> ptr = &Helper;
static void Helper(ref FooStruct instance) => instance.Foo();
delegate* managed<ref FooStruct, void> ptr = &Helper;
otherwise you'll have a hard time calling it correctly anyway. if you really need the actual one, you should be able to use ldftn in IL & you can call it with calli - note that you won't be able to do either of these directly in C#, since C# doesn't support managed instance function pointers (hence why I suggest just making a static wrapper/helper method, since it does support function pointers to managed static methods), you'd have to do it in raw IL or using something like System.Reflection.Emit
akeit0
akeit0OP3w ago
Thanks!! This seems to work.
ldftn instance void Foo::Foo()
ldftn instance void Foo::Foo()
akeit0
akeit0OP3w ago
I need this due to an issue of clrmd. https://github.com/microsoft/clrmd/issues/1306
GitHub
Get ClrMethod from virtual method of struct · Issue #1306 · microso...
xoofx/JitBuddy#3 We can't get ClrMethod of TestStruct.Test by GetMethodByHandle. interface ITest { int Test(); } struct TestStruct: ITest { public int Test() { return 123; } } I think following...
hamarb123
hamarb1233w ago
I think that would give you a function pointer to call Foo on a boxed struct or class that implements IFoo - was that what you were after?
akeit0
akeit0OP3w ago
typo But writing IL is not good. I wish there was an even better way...
hamarb123
hamarb1233w ago
I prefer instance explicit personally: ldftn instance explicit void FooStruct::Foo(FooStruct&) or something like that ideally (it makes it more obvious what all the relevant types are), and then call with calli instance explicit void(FooStruct&) or something like that you can either write a static helper method & do function pointer stuff on that from c#, or use System.Reflection.Emit (not AOT compatible, etc.) or you might be able to create a delegate via reflection iirc @akeit0 here's how you can do it using normal reflection if that works for you: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEUCuA7AHwAEAmARgFgAoIgBgAIiyA6AJXwwEsBbGZgYQjcADpwA2MKAGVJAN05gYAZwDc1agA16CegF56eGAHcAFAEo1VfEoCGAMxjUA3tXpvGZAJwmTASTwYAAoYUGYmRCgAVGYAZAgW1AC+1BgAnsIwEHYmGmbMAOIwGACyRQAWEAAmJgBEAGIQEDV5/LA2GDAAIjASAObtMAA8DRDdYgB85iawdtoJVNSVPTD9HYwo9CNj0zCzWvGW1EohOGAY9BrOru4A9Dd4EB0g9ACqeLYOzACCSoEQnAFJPROEp6BA8GJUvQcEoYJV6BgIPQltxwccoAMEWV2sDziCEbhIfQwDYxGIAb0wXgsY4qO56HcxBASWJkTAwGIbLBKmgDI96DY8FClNBzlliRBhFC4MjwQByc4wmCvd72Pg/P4AjpQejkgDWyowZXxAPobVZkCW1zcRAAzNDVQ51ptGuY9OMPN4/AFgqE3h91b9/oCoDtZkaQWZ5okgA==
akeit0
akeit0OP3w ago
It uses Delegate._methodPtrAux, but it is not the one I need. This works.
public static IntPtr GetMethodPointer(MethodInfo methodInfo)
{
var dynamicMethod = new DynamicMethod("GetFunctionPointer", typeof(IntPtr), [], typeof(MdInternal).Module);
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldftn, methodInfo);
il.Emit(OpCodes.Ret);
return (IntPtr)dynamicMethod.Invoke(null, null)!;
}
public static IntPtr GetMethodPointer(MethodInfo methodInfo)
{
var dynamicMethod = new DynamicMethod("GetFunctionPointer", typeof(IntPtr), [], typeof(MdInternal).Module);
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldftn, methodInfo);
il.Emit(OpCodes.Ret);
return (IntPtr)dynamicMethod.Invoke(null, null)!;
}

Did you find this page helpful?