Hi all,
I'm trying to use GetDelegateForFunctionPointer for a c++ native function. I have this working in Windows, but on Android, the C++ call stack appears to be garbage. I'm sure it has to do with how mono is handling the native argument stack. My guess is that JNICALL (Java) is different than __stdcall (Windows), but GetDelegateForFunctionPointer requires the __stdcall format. Please take a look at SomeFunction() below; it's the call getting garbage argument stack.
C++ (Android NDK) // function called by C# through GetDelegateForFunctionPointer extern "C" JNIEXPORT int JNICALL SomeFunction(int num, float flt, char *msg) { // Windows shows correct arguments, but Android shows garbage arguments m_strdup_printf ("Some Function data '%s'.", msg); return 0; } // calling code using embedded Mono ... MonoMethodDesc* sayHelloDesc = mono_method_desc_new("Class1:ManagedMethodSayHello(string,int,intptr)", false); MonoMethod* sayHelloMeth = mono_method_desc_search_in_class(sayHelloDesc, pClass); if (!sayHelloMeth) { result = -1; return; } char *arg = "Hello World"; int num = 0x64; int(JNICALL *func)(int, float, char *) = &SomeFunction; void * newArgs[3]; newArgs[0] = mono_string_new(mono_domain_get(), arg); newArgs[1] = # newArgs[2] = &func; exc = 0; ret = mono_runtime_invoke(sayHelloMeth, class1Instance, newArgs, &exc); ... c# // delegate pattern that matches 'SomeFunction' argument list delegate int CFuncDelegate(int num, float flt, string msg); public interface InterfaceClass1 { IntPtr ManagedMethodSayHello(string arg, int num, IntPtr func); } public class Class1 : InterfaceClass1 { Class1() { } public IntPtr ManagedMethodSayHello(string arg, int num, IntPtr func) { CFuncDelegate myfunc = (CFuncDelegate)Marshal.GetDelegateForFunctionPointer(func, typeof(CFuncDelegate)); // make the call (Mono handles Marshaling of the string argument in Windows implementation) int res = myfunc(55, 3.14f, "Did you see what I did here?"); return func; }
Incidentally, here's the same working method from Windows
int __stdcall SomeFunction(int num, float flt, char *msg) { COutputWnd::Instance->AppendBuild(CA2W(msg)); return 0; } ... // int ManagedMethodSayHello(string arg, int num, IntPtr func) MonoMethodDesc* sayHelloDesc = mono_method_desc_new("Class1:ManagedMethodSayHello(string,int,intptr)", FALSE); MonoMethod* sayHelloMeth = mono_method_desc_search_in_class(sayHelloDesc, pClass); if (!sayHelloMeth) { result = -1; return; } char *arg = "Hello World"; int num = 0x64; int(__stdcall *func)(int num, float flt, char *) = &SomeFunction; void * newArgs[3]; newArgs[0] = mono_string_new(mono_domain_get(), arg); newArgs[1] = # newArgs[2] = &func; exc = 0; ret = mono_runtime_invoke(sayHelloMeth, class1Instance, newArgs, &exc); ...