如何为单声道运行时在C中创建接口实现的委托?

时间:2018-08-15 14:37:34

标签: c# c mono interop

我正在尝试使用mono使用某些c#(或f#)代码扩展用Linux编写的c语言库。

从c调用c#的简单示例看起来很简单:

//c# code, compiled with mcs -t:library Ex1.cs
public static class Ex1 {
  public class Inner {
    public static void someAction(int i) {
      System.Console.WriteLine("some action with " + i);
    }
  }
}

//c code, compiled with gcc ex1.c $(pkg-config --cflags --libs mono-2)
#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>

int main()
{
  MonoDomain *domain = mono_jit_init("Ex1.dll");
  MonoAssembly *assembly = mono_domain_assembly_open(domain, "Ex1.dll");
  MonoImage *image = mono_assembly_get_image(assembly);

  MonoClass *class_ptr = mono_class_from_name(image, "", "Ex1/Inner");
  MonoMethod *class_method = mono_class_get_method_from_name_flags(
      class_ptr, "someAction", 1, 0);

  void *args[1];
  int value = 42;
  args[0] = &value;
  mono_runtime_invoke(class_method, NULL, args, NULL);

  mono_jit_cleanup(domain);
  return 0;
}

正在运行./a.out,我们看到了c#库的输出。

但是有可能在c端实现接口或至少在c#中定义的委托吗?

例如:

//c# compiled mcs -t:library Ex2.cs
public static class Ex2 {
  public interface MyInterface {
    void someAction(int i);
  }

  public delegate void MyDelegate(int i);

  public static class Inner {
    static public void someAction1(MyInterface iface, int value) {
      iface.someAction(value);
    }
    static public void someAction2(MyDelegate d, int value) {
      d(value);
    }
  }
}


//c compiled with gcc ex2.c $(pkg-config --cflags --libs mono-2)
#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>

int main()
{
  MonoDomain *domain = mono_jit_init("Ex2.dll");
  MonoAssembly *assembly = mono_domain_assembly_open(domain, "Ex2.dll");
  MonoImage *image = mono_assembly_get_image(assembly);

  MonoClass *class_ptr = mono_class_from_name(image, "", "Ex2/Inner");
  MonoMethod *class_method1 = mono_class_get_method_from_name_flags(
      class_ptr, "someAction1", 2, 0);
  MonoMethod *class_method2 = mono_class_get_method_from_name_flags(
      class_ptr, "someAction2", 2, 0);

  void *args1[2];
  int value1 = 42;
  args1[0] = NULL;//how to correctly initialize this?
  args1[1] = &value1;
  mono_runtime_invoke(class_method1, NULL, args1, NULL);

  void *args2[2];
  int value2 = 42;
  args2[0] = NULL; //or this?
  args2[1] = &value2;
  mono_runtime_invoke(class_method2, NULL, args2, NULL);

  mono_jit_cleanup(domain);
  return 0;
}

谢谢。

0 个答案:

没有答案