4

Binding ObjectiveC Class to C# problem

The monotouch project describes how to bind Objective-C Types for use with MonoTouch. We failed to do this for the AdMob library (see also the monotouch-binding-for-admob blog at sabonrai dot wordpress dot com.

So we decided to create the smallest possible test project. We wrote a simple objc class with two simple methods, one that returns a string, and one that returns an integer.

Here's the TstLib.h:

#import <Cocoa/Cocoa.h>
@interface TstCls : NSObject {
}
- (NSString *) Version;
- (int) GimmeAnInt;
@end

and the TstLib.m file:

#import "TstCls.h"
@implementation TstCls
- (NSString *) Version {
    return @"I ain't got a version, I'm a poor lonesome cowboy...";
}
- (int) GimmeAnInt {
    return 110646;
}
@end

We've got a little objc console project to validate this library. Here's the code:

#import <Cocoa/Cocoa.h>
#import "../TstLib/TstCls.h"
int main(int argc, char *argv[])
{
    TstCls* tstCls = [[TstCls alloc] init];
    NSLog(@"version = %@", [tstCls Version]);
    NSLog(@"the int = %d", [tstCls GimmeAnInt]);
    return NSApplicationMain(argc,  (const char **) argv);
}

So, let's define a binding file for the btouch utility.

using MonoTouch.Foundation;
namespace TstLib {
  [BaseType (typeof (NSObject))]
    interface TstCls {
      [Export ("Version")]
      string Version ();
      [Export ("GimmeAnInt")]
      int GimmeAnInt ();
    }
}

We then create a libTstLib.a and a TstLib.dll file with the btouch utility:

/Developer/MonoTouch/usr/bin/btouch -o TstLib.dll TstCls.cs

We now create a new Monotouch window based iphone app 'ApiTest', add a Lib directory with the libTstLib.a and the TstLib.dll files, add a reference to this TstLib.dll and integrate our TstLib into the Main.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using TstCls;
namespace ApiTest
{
  // -gcc_flags "-L${ProjectDir}/Lib -lTstLib -ObjC"
  // or
  // -gcc_flags "-L${ProjectDir}/Lib -lTstLib -force_load ${ProjectDir}/Lib/libTstLib.a"
  public class Application
  {
    static void Main (string[] args)
    {
      UIApplication.Main (args);
    }
  }
  // The name AppDelegate is referenced in the MainWindow.xib file.
  public partial class AppDelegate : UIApplicationDelegate
  {
    // This method is invoked when the application has loaded its UI and its ready to run
    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
      // If you have defined a view, add it here:
      // window.AddSubview (navigationController.View);

      TstLib.TstCls tstCls = new TstLib.TstCls ();
      Console.WriteLine ("TstLib.TstCls.Version() -> '{0}'", tstCls.Version ());
      Console.WriteLine ("TstLib.TstCls.GimmeAnInt() -> '{0}'", tstCls.GimmeAnInt ());
      window.MakeKeyAndVisible ();
      return true;
    }
    // This method is required in iPhoneOS 3.0
    public override void OnActivated (UIApplication application)
    {
    }
  }
}

This little project runs without the two Console.Writeline statements. It crashes without any output as soon as one of the Console.WriteLine statements is executed.

We've tried to be as concise as possible, still providing enough info to recreate the test case. We're very willing to provide any additional info to help fix this.

Does anybody see why this does not work as expected? We've limited ourselves to the bare minimum to test whether we can provide and use a binding for a minimal ObjC class.

Unfortunately it fails. And it fails in the same way as the MT_SampleAdMob project described in the monotouch-binding-for-admob blog.

Our little project uses the btouch approach described at monotouch dot net under heading Binding_New_Objective-C_Types whereas the MT_SampleAdMob project uses the 'manual' approach described at the same location.

Both approaches fail in a similar matter. As soon as a class or instance method is called, the app just crashes without any output.

We've got no idea what can be done to pinpoint this problem and come to a solution. Monotouch provides c# bindings for many of the ObjC classes, so it must be possible. We've carefully studied the MonoTouch docs referenced above. We fail to see where either the MT_SampleAdMob or this btouch approach would deviate from the prescribed procedure, and yet both fail!

So really, we desperately need some help here...

Will Marcouiller
  • 23,773
  • 22
  • 96
  • 162
guivho
  • 365
  • 1
  • 2
  • 18

1 Answers1

6

You likely didn't disable THUMB mode for your native library. Ever since iOS SDK 3.0 the apple linker has problems linking Thumb libraries into larger projects.

You can disable thumb mode by opening your native library in Xcode and doing the following:

  1. Project -> Edit Project Settings
  2. Type "thumb" in "Search in Build Settings"
  3. Uncheck box
  4. Rebuild your native library.
Geoff Norton
  • 5,056
  • 1
  • 19
  • 17
  • Geoff, Of course, you were right. I forgot about the thumb thing. I had seen postings mentioning this aspect, but never saw a clear concise explanation about it. After applying this to my little test library, the iPhone test succeeded. So I will now try to work this out for the AdMob library and I will post my findings here. Thanks for your help, Mollyke. – guivho Nov 24 '10 at 08:41