[Mono-osx] Invoke CIL/Managed Code from ObjC/XCode on Mac
Kevin Heeney
koheeney at gmail.com
Tue Oct 28 23:51:58 EDT 2008
Thank you very much. Between your post (Duane) and the post from
Andreas (and the embed mono page at <http://www.mono-project.com/
Embedding_Mono>), I have been able to successfully call my C#
methods from ObjC in XCode as well as get return values from
functions and values from public variables. Now I am in the process
of writing a couple of Objective-C wrapper classes to invoke methods
in my C# classes.
Since I am doing my front end using Objective-C and my model in C#, I
was going to write an Objective-C Wrapper generator in C# that would,
via reflection, analyze my .NET classes and generate Objective-C code
that I could use as wrappers to invoke those classes. Atleast a
simple version that would support primitive types. Before I started
on this, I wanted to see if anyone knows of something like this that
has been done. I have found plenty of ways to call Cocoa from C#,
but I don't think I am aware of anything to go the other way.
Thanks again.
Kevin
On Oct 25, 2008, at 8:22 AM, Duane Wandless wrote:
> I will share what works for me. First I use monobjc. Great
> documentation. Easy to use. Well supported. I am using the
> latest mono install 2.0, though this worked with 1.9 as well. And
> I use Xcode 3.1. I place my mono EXE in build/Debug/MyCocoa.app/
> Content/Libraries, along with the Monobjc DLLs. As you will see in
> the code (main.m) below, I load the EXE relative to the app bundle
> location.
>
> For me anyway I hit a bug in 2.0 that required me to load an EXE
> rather than a DLL. In some ways the EXE is better. I have a
> Program.cs (see below) that initializes the MonoObjc environment.
> It is important to load the MonoObjc environment prior to Cocoa
> setting up the IB references. This way when the NIB file is loaded
> it will find your [ObjectiveCClass] references, see MainForm.cs
> below, which is snippets only.
>
> In my NIB file I have an object that has its class MonoMessage. I
> hookup the array, tree, outline view, fields, etc to this object.
> At runtime they are hooked up to my mono class. I have some objC
> code (MainDocument.m below) that sends messages to my mono class.
> And my mono class sends messages back to the objC world.
>
> We wanted the best of both worlds. The power of C# and the ability
> to reuse the code on Mac and Windows. But we also wanted the
> native build environment for the Leopard frontend. So not only was
> using IB a requirement but so was writing the UI code in objC.
> Thanks to mono and monobjc we accomplished this with a very clean
> environment.
>
> You can also take the mono EXE and fully embed it within the cocoa
> app. This way the end user is not required to install mono. But
> that is a topic for a different thread.
>
> Other C Flags = -D_THREAD_SAFE -D_REENTRANT -I/Library/Frameworks/
> Mono.framework/Versions/2.0/include/mono-1.0 -I/Library/Frameworks/
> Mono.framework/Versions/2.0/include/glib-2.0 -I/Library/Frameworks/
> Mono.framework/Versions/2.0/lib/glib-2.0/include
> Other C++ Flags = $(OTHER_CFLAGS)
> OTHER_LDFLAGS = -pthread -L/Library/Frameworks/Mono.framework/
> Versions/Current/lib -lmono -lpthread -lm -lgthread-2.0 -lglib-2.0 -
> lintl -rpath at loader_path/../Libraries
>
>
> main.m:
> #import <Cocoa/Cocoa.h>
> #include <mono/jit/jit.h>
> #include <mono/metadata/assembly.h>
> #include <mono/metadata/mono-config.h>
>
> int main(int argc, char *argv[])
> {
> NSAutoreleasePool *pool;
> pool = [[NSAutoreleasePool alloc] init];
>
> MonoDomain *domain;
> NSString *libraryPath = [[[NSBundle mainBundle] bundlePath]
> stringByAppendingPathComponent:@"Contents/Libraries"];
> NSString *sampleAssemblyPath = [libraryPath
> stringByAppendingPathComponent:@"MacMonoClient.exe"];
> NSLog(@"libraryPath: %@", sampleAssemblyPath);
> mono_config_parse ("config");
> domain = mono_jit_init ([sampleAssemblyPath UTF8String]);
> MonoAssembly *monoAssembly = mono_domain_assembly_open(domain,
> [sampleAssemblyPath UTF8String]);
> mono_jit_exec (domain, monoAssembly, 1, argv);
> NSLog(@"sample assembly: %p", monoAssembly);
> [pool release];
>
> return NSApplicationMain(argc, (const char **) argv);
> }
>
> Program.cs:
> using System;
> using Monobjc;
> using Monobjc.Cocoa;
>
> namespace MacClient
> {
> static class Program
> {
> public static void Main()
> {
> ObjectiveCRuntime.LoadFramework("Cocoa");
> ObjectiveCRuntime.LoadFramework("QTKit");
> ObjectiveCRuntime.Initialize();
> }
> }
> }
>
> MainForm.cs:
> using System;
> using Monobjc;
> using Monobjc.Cocoa;
> using Monobjc.QuickTime;
>
> namespace MacClient
> {
> [ObjectiveCClass("MonoMessage")]
> public class MyControl : NSObject
> {
> private static readonly Class ControllerClass =
> Class.GetClassFromType(typeof(MyControl));
>
> public MyControl() { }
> public MyControl(IntPtr np) : base(np) { }
>
> NSAutoreleasePool pool = new NSAutoreleasePool();
> ~MyControl()
> {
> pool.Drain();
> }
>
> [ObjectiveCField]
> public NSArrayController projectsController;
> [ObjectiveCField("itemsController")]
> public NSTreeController folderContent;
> [ObjectiveCField]
> public NSOutlineView folderOutline;
>
> [ObjectiveCMessage("init")]
> public override Id Init()
> {
> ObjectiveCRuntime.SendMessageSuper<IntPtr>(this,
> ControllerClass, "init");
>
> NSNotificationCenter.DefaultCenter.AddObserverSelectorNameObject
> (this, ObjectiveCRuntime.Selector("doAuth:"), "doAuth", null);
> }
> [ObjectiveCMessage("awakeFromNib")]
> public void awakeFromNib()
> {
> }
> [ObjectiveCMessage("doAuth:")]
> public void SelectionChanged(NSNotification notification)
> {
> NSArray loginParms = notification.UserInfo.ObjectForKey
> (new NSString("params")).CastTo<NSArray>();
> Login(loginParms[0].CastTo<NSString>(), loginParms
> [1].CastTo<NSString>());
> }
> }
> }
>
> MainDocument.m
> - (IBAction)login:(id)sender
> {
> NSLog(@"Starting login process...");
>
> NSString *username = [usernameTextField stringValue];
> NSString *password = [passwordTextField stringValue];
>
> NSArray *loginParams = [NSArray arrayWithObjects:username,
> password, nil];
> NSDictionary* dict = [NSDictionary
> dictionaryWithObject:loginParams forKey:@"params"];
> NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
> [nc postNotificationName:@"doAuth" object:nil userInfo:dict];
> }
>
> On Fri, Oct 24, 2008 at 10:13 PM, Kevin Heeney <koheeney at gmail.com>
> wrote:
> I think I have hit a wall. I am fairly new to mono on mac;
> however am familiar with .NET and Objc/Cocoa. I am unable to
> successfully 'embed mono' or call methods from my Mono dll in
> ObjC. I have created a UI using Interface Builder and have my App
> Controller in ObjC ready to call my C# dll which contains my
> logic. Cocoa# and ObjCSharp both claim to be 2 way bridges;
> however I can only find code for calling Cocoa from C# and not the
> other way around. In addition, I cannot get the samples from
> <http://www.mono-project.com/Embedding_Mono> on Embedding Mono to
> work in XCode. My actual issue with the latter is I cannot get
> XCode to link to the mono framework. I am getting errors like
> "main.c:1: error: mono/jit/jit.h: No such file or directory".
> I am not sure what I am missing; it may be simple.
>
> Any guidance would be appreciated.
> Thanks,
> Kevin
>
> _______________________________________________
> Mono-osx mailing list
> Mono-osx at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-osx
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-osx/attachments/20081028/9c2cafbd/attachment.html
More information about the Mono-osx
mailing list