Bruno,
Marshal.GetDelegateFromFunctionPointer() and mono_ftnptr_to_delegate
only work on functions with p/invoke-compatible signatures.
This means that you can't pass MonoObjects* to these functions.
You can only declare and pass p/invoke-compatible arguments.
There is also no *this* pointer available.
If you want a signature like this
MonoBoolean testMethod(MonoString *arg2)
then you must declare a C# helper for it:
namespace EmbeddingHelpers
{
class DelegateHelper
{
public static Func CreateDelegate()
{
return TestMethod;
}
[MethodImpl(MethodImplOptions.InternalCall)]
static bool extern TestMethod(string arg);
}
}
C++:
MonoBoolean TestMethodInternal(MonoString* arg)
{
return TRUE;
}
mono_add_internal_call("EmbeddingHelpers.DelegateHelper::TestMethod");
The delegate can be finally obtained from the static method
EmbeddingHelpers.DelegateHelper.CreateDelegate();
There might be better/elegant ways to do this, but they all
need an InternalCall declaration. There is no other way to tell
mono to wrap a native function to support native (embedded mono)
calls.
Robert
On 08.08.2014 19:29, Bruno Lauze wrote:
Hi,
I am sure someone can help me out. At one point this code did work. I
changed something and/or I just reinstalled latest trunk and it broke.
I am trying to pass C delegate to C#. Everything is working C# is calling
back the method but the parameters seems to be invalid pointers.
The C delegate was returning the delegate object, and the parameters.
I did put mono_ftnptr_to_delegate to external removing MONO_INTERNAL and
placing it under MONO_API.
One could use Marshal.GetDelegateFromPointer with mono_runtime_invoke
(Adding that way too at the bottom.)
Consider the following code:
DelegateHelper.dll: MyClass.cs:
using System;
namespace DelegateHelper
{
public delegate bool TestDelegate(string arg1);
public class MyClass
{
public static bool Test(TestDelegate predicate)
{
return predicate("TEST");
}
}
}
main.c:
#include
#include
#include
#include
#include
#include
#include
#include
MONO_API MonoDelegate*
mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn);
MonoBoolean testMethod(MonoObject *arg1, MonoObject *arg2)
{
printf("Calling delegate!");
MonoString *str = mono_object_to_string(arg2, NULL); //crash
return TRUE;
}
int main (int argc, char *argv[])
{
printf ("Delegate Test!\n");
MonoDomain *domain = mono_jit_init_version("DelegateTest",
"v4.0.30319");
mono_config_parse(NULL);
void *__parameters__[1];
MonoAssembly *ass = mono_assembly_open("DelegateHelper.dll", NULL);
MonoImage *image = mono_assembly_get_image(ass);
MonoClass *delegateClass = mono_class_from_name(image,
"DelegateHelper", "TestDelegate");
mono_class_init(delegateClass);
MonoClass *testClass = mono_class_from_name(image, "DelegateHelper",
"MyClass");
mono_class_init(testClass);
gpointer ptr = (gpointer)testMethod;
MonoDelegate *delegateObj = mono_ftnptr_to_delegate(delegateClass,
ptr); //Short way to call Marshal.GetDelegateFromFunctionPointer()
MonoMethod *testMethod = mono_class_get_method_from_name(testClass,
"Test", 1);
__parameters__[0] = delegateObj;
MonoObject *result = mono_runtime_invoke(testMethod, NULL,
__parameters__, NULL);
return 0;
}
Result:
Delegate Test!
Calling delegate!
Stacktrace:
at <0x>
at (wrapper managed-to-native) object.wrapper_native_0x40ea40 ()
<0x>
at DelegateHelper.MyClass.Test (System.Func`2) <0x00018>
at (wrapper runtime-invoke) .runtime_invoke_bool_object
(object,intptr,intptr,intptr) <0x>
=
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=
Abort
This code could be used instead of mono_ftnptr_to_delegate which is normally
internal
/*
MonoImage *mscorlib =
mono_assembly_get_image(mono_domain_assembly_open(domain, "mscorlib"));
MonoClass *marshal = mono_class_from_name(mscorlib,
"System.Runtime.InteropServices", "Marshal");
MonoMethod *getDelegate = mono_class_get_method_from_name(marshal,
"GetDelegateForFunctionPointer", 2);
void *marshal_params[2];
marshal_params[0] = ptr;
marshal_params[1] = mono_type_get_object(domain,
mono_class_get_type(delegateClass));
MonoObject *delegateObj = mono_runtime_invo