将C#与Objective-C混合

Fil*_*unc 29 c# mono cocoa objective-c

我想使用更大的C#代码作为Objective-C(Cocoa)应用程序的库.

我发现了包装Cocoa代码的MonoMac项目,但我宁愿用Objective-C编写标准的Cocoa应用程序,它可以调用包装好的C#代码(换句话说).

在Windows上,我习惯于制作包含.NET代码的C++/CLI项目,并为基于C/C++的应用程序导出普通的旧C接口.

有一些简单的方法来实现这一目标吗?

zne*_*eak 16

显然,在Mac OS上没有像C++/CLI这样的语言.在Windows上,C++/CLI实际上编译为CLR运行的托管代码,运行本机代码; 因为在Mac OS Mono上没有集成到系统中,所以它恰恰相反.您的应用是原生的,它可以托管托管代码.

Mono公开了在进程内托管CLR虚拟机的函数.由于CLR类没有直接暴露给您的C代码,因此您将能够通过类似反射的调用来调用对象的方法.

关于如何将Mono嵌入官方网站上的应用程序的文档.由于您对直接运行.NET程序不感兴趣,因此您应该阅读"在CIL Universe中调用方法"部分.在Mac OS上,您需要从/Library/Frameworks文件夹链接Mono框架,而不是使用pkg-config.

这实际上不应取代上述文件的实际阅读,但以下内容可视为预期内容的指南:

#include <glib/glib.h>
#include <mono/jit/jit.h>
#include <mono-metadata/assembly.h>
#include <mono/metadata/debug-helpers.h>

// create an app domain
// http://en.wikipedia.org/wiki/Application_Domain
MonoDomain* domain = mono_jit_init("Domain");

// mandatory Cocoa call to show that Mono and ObjC work together
NSBundle* mainBundle = [NSBundle mainBundle];
NSString* dll = [mainBundle pathForResource:@"your-dll" ofType:@"dll"];

// load the referenced assembly in our domain
MonoAssembly* assembly = mono_domain_assembly_open(domain, [dll UTF8String]);
MonoImage* image = mono_assembly_get_image(assembly);

// find the class we want to wrap and create an uninitialized instance
MonoClass* classHandle = mono_class_from_name(image, "Name.Space", "YourClass");
MonoObject* object = mono_object_new(domain, classHandle);

// this calls the default, argument-less ctor
// for more complex constructors, you need to find the method handle and call it
// (helpful hint: constructors are internally called ".ctor", so the description
// string will look like "Namespace.Class..ctor()")
mono_runtime_object_init(object);

// get a method handle to whatever you like
const char* descAsString = "Your.NameSpace.YourClass:YourMethod()";
MonoMethodDesc* description = mono_method_desc_new(descAsString);
MonoMethod* method = mono_method_desc_search_in_class(description, classHandle);

// call it
void* args[0];
mono_runtime_invoke(method, object, args, NULL);

// when you're done, shutdown the runtime by destroying the app domain
mono_jit_cleanup(domain);
Run Code Online (Sandbox Code Playgroud)

如果您没有发现这非常吸引人,您可能想要反过来,如您所述,并查看MonoMac,它提供.NET绑定到您可能想要在Mac应用程序中使用的大部分API (Cocoa,CoreImage,CoreAnimation等)并且意味着创建自己的绑定.

  • @Filip Kunc是的,我知道.人们总是抱怨C++/CLI,尽管它实际上是混合托管代码和本机代码的好方法.但是,除了非常冗长之外,嵌入Mono并不是那么糟糕,因为大多数调用只执行一次(你将重用`MonoDomain`,`MonoAssembly`,`MonoImage`,`MonoClass`和`MonoMethod`句柄).如果你已经使用高级语言的运行时函数(这是一个很大的if),那么这里没什么可惊讶的. (2认同)