我想将更大的C#代码体用作Objective-C(Cocoa)应用程序的库。
我发现了包装 cocoa 代码的MonoMac项目,但我宁愿用Objective-C编写标准的Cocoa应用程序,该应用程序可以调用包装的C#代码(反之亦然)。
在Windows上,我习惯于制作C++/CLI项目,该项目包装.NET代码并导出基于C/C++的应用程序的纯旧C接口(interface)。
有一些简单的方法可以做到这一点吗?
最佳答案
显然,在Mac OS上没有C++/CLI这样的语言。在Windows上,C++/CLI实际上是由运行 native 代码的CLR运行的托管代码编译的。由于在Mac OS Mono上没有集成到系统中,因此反之亦然。您的应用程序是本地应用程序,它可以托管托管代码。
Mono公开了在进程内部托管CLR虚拟机的函数。由于CLR类没有直接暴露给C代码,因此您可以通过类似于反射的调用来调用对象的方法。
官方网站上有documentation on how to embed Mono into an application。由于您对running .NET programs directly不感兴趣,因此您应该阅读"Invoking Methods in the 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 "Name.Space.Class:.ctor()")
mono_runtime_object_init(object);
// get a method handle to whatever you like
const char* descAsString = "Name.Space.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);
如果您觉得这不是很吸引人,则可以按照您提到的方法进行另一种研究,并查看MonoMac,它为您可能要在Mac应用程序中使用的大部分API提供了.NET绑定(bind)。 ( cocoa ,CoreImage,CoreAnimation等),并表示创建自己的绑定(bind)。
关于c# - 将C#与Objective-C混合,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5692813/