Search code examples
interfacemonomono-embedding

How to invoke an interface method with Mono Embedding?


I load an assembly and from that a class of the object I want to create. From that class I check for interfaces (mono_class_get_interfaces) and find the interface class I want (IDispose).

I create the object with mono_object_new and call mono_runtime_object_init directly afterward. I then call mono_object_castclass_mbyref to cast the object to an interface reference. Then I retrieve the interface method I want to call (Dispose) from the interface class with mono_class_get_method_from_name.

I call mono_object_get_virtual_method to make sure I have the correct implementation and then try to call it with mono_runtime_invoke using the interface MonoObject * reference and the interface virtual method MonoMethod * (args = NULL) -> which is unsuccessful.

I have also tried to call mono_method_get_unmanaged_thunk with the same parameter, that doesn't work either.

In both cases I get a value back for the exception argument. Problem is, I haven't found a way to look inside the exception...

Question is:

  1. Is the sequence of calls correct to work with managed interfaces and call the correct (most specific) interface methods?
  2. How to get more information on the MonoException (I assume the MonoObject * returned by invoke is a MonoException instance)?

Solution

  • There is no need to invoke any castclass function to cast a managed reference to an 'interface reference': the value is the same.

    Once you have your IDispose MonoClass* pointer, you should get the MonoMethod* for the method you want to call and pass that to mono_object_get_virtual_method(). The result of this function is what you should pass to mono_runtime_invoke().

    For the exception, you can invoke the get_Message method method, for example, or any of the methods you'd call to deal with it if you were in C# code.

    Simple tested code below, str is a MonoString*:

    icloneable_class = mono_class_from_name (mono_get_corlib (), "System", "ICloneable");
    iface_method = mono_class_get_method_from_name (icloneable_class, "Clone", 0);
    iface_impl_method = mono_object_get_virtual_method (str, iface_method);
    exc = NULL;
    obj = mono_runtime_invoke (iface_impl_method, str, NULL, &exc);
    

    The method is correctly invoked and exc will be NULL.