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@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list



_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to