31 votes

Mélange de C # avec Objective-C

Je voudrais utiliser un plus grand corps de code C # comme bibliothèque pour l'application Objective-C (Cocoa).

J'ai découvert le projet MonoMac qui encapsule le code Cocoa, mais je préfère avoir une application Cocoa standard écrite en Objective-C, qui peut appeler du code C # encapsulé (l'inverse).

Sous Windows, j'ai l'habitude de créer un projet C ++ / CLI qui enveloppe le code .NET et exporte une ancienne interface C simple pour les applications basées sur C / C ++.

Existe-t-il un moyen simple d'y parvenir?

18voto

zneak Points 45458

Il y a, évidemment, aucune de ces langues en tant que C++/CLI sur Mac OS. Sur Windows, C++/CLI effectivement compile en code managé couru par le CLR, qui s'exécute du code natif; depuis sur Mac OS Mono n'est pas intégré dans le système, c'est plutôt l'inverse. Votre application est originaire, et il peut accueillir de code managé.

Mono expose les fonctions d'accueillir un CLR de la machine virtuelle à l'intérieur d'un processus. Depuis CLR classes ne sont pas directement exposés à votre code en C, vous serez en mesure d'appeler les méthodes des objets par le biais de la réflexion, comme les appels.

Il y a de la documentation sur la façon d'intégrer Mono dans une application sur le site officiel. Puisque vous n'êtes pas intéressé, en cours d'exécution .NET des programmes directement, vous devriez plutôt lire le "Invoquer les Méthodes dans le CIL de l'Univers" section. Sur Mac OS, vous aurez envie de le lier avec le framework Mono à partir de votre /Library/Frameworks le dossier, au lieu d'utiliser pkg-config.

Cela ne devrait pas remplacer une lecture du document ci-dessus, mais ce qui suit peut être considéré comme un guide à quoi s'attendre:

#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);

Si vous ne trouvez pas cela très attrayante, vous pouvez aller dans l'autre sens, comme vous l'avez mentionné, et regarder dans les MonoMac, qui fournit .NET de liaisons pour une grande partie de l'Api que vous pouvez utiliser dans une application Mac (Cacao, CoreImage, CoreAnimation, etc) et des moyens pour créer votre propre liaisons.

3voto

Jiva DeVoe Points 620

Si vous ne le faites pas sur Mac, alors oui, c'est possible. Sur iOS, pas tellement.

Sur le Mac, si vous pouvez créer un CLI application dans MonoMac, alors vous pouvez appeler votre CLI application à partir de l'intérieur de votre Objectif-C application à l'aide de NSTask. NSTask vous permet de lancer facilement une ligne de commande outil et le capturer à la sortie et d'interagir avec elle. Pour ce faire, vous devez faire quelque chose comme:

NSArray *args = [NSArray arrayWithObjects:@"-arg1", @"-arg2", nil];
NSTask *foo = [[NSTask alloc] init];
[foo setLaunchPath:@"/usr/bin/foo"];
[foo setArguments:args];

NSPipe *pipe = [NSPipe pipe];
[foo setStandardOutput:pipe];

NSFileHandle *output = [pipe fileHandleForReading];

[foo launch];

NSData *data = [output readDataToEndOfFile];

NSString *outputStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"Got stuff: %@", outputStr);

Généralement, la façon dont vous voulez le faire, est de vous inclure à la CLI d'application à l'intérieur de votre app bundle. Ensuite, vous pouvez obtenir le chemin d'accès à la CLI d'application à l'aide de NSBundles -pathForResource:ofType: la méthode.

iOS ne comprend pas le NSTask API, donc ce n'est pas possible. J'ai entendu parler de certaines personnes à l'aide de MonoTouch pour faire des applications iOS à l'aide de C#, mais comme vous l'avez suggéré, je pense que vous êtes mieux de rester avec Objective-C pour la majeure partie de votre application, si possible. À l'aide d'une CLI application comme vous décrivez est certainement une option sur Mac et peut être particulièrement utile lorsque vous avez un corps de code qui est déjà écrit et testé et fonctionne que vous voulez juste pour "Envelopper" avec un Cacao de l'interface graphique.

Donc, NSTask est une façon de faire cela à l'aide d'une CLI exécutable enveloppé dans votre application bundle. D'autre part, vous demandez peut-être, pouvez-vous lier votre code C# directement en Objective-C?

Eh bien, Objective-C est un sur-ensemble de C, et en tant que tel, il dispose de toutes les capacités de C. en Outre, si vous utilisez Objective-C++, il a toutes les fonctionnalités de C++. Donc, SI vous pouvez obtenir MonoMac pour générer un C ou C++ statique de la bibliothèque, alors oui, vous pouvez même juste un lien de votre bibliothèque statique avec votre Objectif-C de cacao code, et il va tout simplement de travail. Je ne peux pas vous dire comment faire de la bibliothèque de MonoMac, mais faire des liens, c'est juste une question de l'ajouter à vos bibliothèques liées dans vos paramètres de construction dans Xcode.

EDIT: je ne suis pas familier avec le C++/CLI est comme une langue, et j'ai mal interprété le sens de C++/CLI pour dire "C++ Interface de Ligne de Commande app". Cela dit... les techniques que j'ai décrit toujours appliquer les méthodes possibles pour faire ce que vous voulez faire, mais il n'est PAS en utilisant le C++/CLI interface comme vous pouvez le faire sur Windows.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X