[Mono-dev] mono_fntptr_to_delegate

Robert Jordan robertj at gmx.net
Fri Aug 8 18:55:36 UTC 2014


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<string, bool> 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 <stdio.h>
>
> #include <glib.h>
>
> #include <mono/jit/jit.h>
>
> #include <mono/metadata/object.h>
>
> #include <mono/metadata/reflection.h>
>
> #include <mono/metadata/assembly.h>
>
> #include <mono/metadata/threads.h>
>
> #include <mono/metadata/mono-config.h>
>
>
>
> 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 <unknown> <0xffffffff>
>
>    at (wrapper managed-to-native) object.wrapper_native_0x40ea40 ()
> <0xffffffff>
>
>    at DelegateHelper.MyClass.Test (System.Func`2<string, bool>) <0x00018>
>
>    at (wrapper runtime-invoke) <Module>.runtime_invoke_bool_object
> (object,intptr,intptr,intptr) <0xffffffff>
>
>
>
> =================================================================
>
> 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_invoke(getDelegate, NULL,
> marshal_params, NULL);
>
>          */
>
>
>
>
>
> Please help!!
>
>
>
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>




More information about the Mono-devel-list mailing list