Felix Ruzzoli
Felix Ruzzoli

Reputation: 91

Creating Xamarin iOS Bindings for classes and procotols

The Goal

We are trying to compile a recent fork of the route-me iOS SDK (Alpstein, MapBox or xmap) and create a Xamarin Binding Project from that.

The code we already tried can be found at these repositories (in descending order of freshness):

The Problem

Unfortunately we are stuck at a pretty initial stage. route-me needs a TileSource to supply the tiles which are to be drawn on the canvas. So we need to expose the RMAbstractWebMapSource class to our C# Xamarin client code via the bindings. Since this class inherits from the RMAbstractMercatorTileSource class, we need to bind that one, too. At last we have to bind the RMTileSource protocol which RMAbstractMercatorTileSource implements.

Below are the definitions of the relevant classes and protocols in the Objective-C source:

RMAbstractWebMapSource

Abstract class defined in RMAbstractWebMapSource.h

@interface RMAbstractWebMapSource : RMAbstractMercatorTileSource

RMAbstractMercatorTileSource

Abstract class defined in RMAbstractMercatorTileSource.h

@interface RMAbstractMercatorTileSource : NSObject <RMTileSource>

RMTileSource

Protocol defined in RMTileSource.h

@protocol RMTileSource <NSObject>

C#-Bindings

[BaseType (typeof (RMAbstractMercatorTileSource))]
public partial interface RMAbstractWebMapSource { ... }

[BaseType (typeof (NSObject))]
public partial interface RMAbstractMercatorTileSource : RMTileSource { ... }

[Model, Protocol, BaseType (typeof (NSObject))]
public partial interface RMTileSource { ... }

These Bindings compile fine. But at runtime..

Client Code Usage

RMAbstractWebMapSource tileSource = new MyTileSource(1234);

Where MyTileSource is defined as:

public sealed class MyTileSource: RMAbstractWebMapSource { ... }

The Error

The following run-time error gets thrown upon instantiation of a MyTileSource object (constructor call), simultaneously crashing the app:

NSForwarding: warning: object [0x...] of class 'MyProject_MyTileSource' does not implement methodSignatureForSelector: -- trouble ahead
NSForwarding: warning: object [0x...] of class 'MyProject_MyTileSource' does not implement doesNotRecognizeSelector: -- abort

Trails

trouble ahead

This error message can be found via Google (eg. http://www.touch-code-magazine.com/does-not-implement-methodsignatureforselector-trouble-ahead/). The answers found on the web indicate a problem with inheritance. It seems as though the MyTileSource class does not inherit from NSObject as it should. However, the generated code from the Xamarin Bindings project (found in ProjectDir/obj after a build) suggests otherwise:

public unsafe abstract partial class RMAbstractWebMapSource : RMAbstractMercatorTileSource { ... }
public unsafe partial class RMAbstractMercatorTileSource : NSObject, IRMTileSource { ... }
public unsafe partial class RMTileSource : NSObject, IRMTileSource { ... }
public interface IRMTileSource : INativeObject, IDisposable { ... }

selector

We could not determine which selector failed. Trying to override void DoesNotRecognizeSelector(Selector sel) in MyTileSource yields a vaguely different error:

NSForwarding: warning: object [0x...] of class 'MyProject_MyTileSource' does not implement methodSignatureForSelector: -- trouble ahead
...(200x)...
NSForwarding: warning: object [0x...] of class 'MyProject_MyTileSource' does not implement methodSignatureForSelector: -- trouble ahead

And finally the native code crashes with a segmentation fault (SIGSEGV). We alse get a stacktrace from the mono runtime this time around. It basically starts at the invocation of the constructor of MyTileSource and dies in NSObject, as far as we can see:

mono-rt:   at <unknown> <0xffffffff>
mono-rt:   at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging.intptr_objc_msgSend (intptr,intptr) <IL 0x00026, 0xffffffff>
mono-rt:   at MonoTouch.Foundation.NSObject.AllocIfNeeded () [0x00015] in /Developer/MonoTouch/Source/maccore/src/Foundation/NSObject2.cs:390
mono-rt:   at MonoTouch.Foundation.NSObject..ctor (MonoTouch.Foundation.NSObjectFlag) [0x00006] in /Developer/MonoTouch/Source/maccore/src/Foundation/NSObject2.cs:102
mono-rt:   at XMap.RMAbstractMercatorTileSource..ctor (MonoTouch.Foundation.NSObjectFlag) <IL 0x00002, 0x0002b>
mono-rt:   at XMap.RMAbstractWebMapSource..ctor () <IL 0x00006, 0x00033>
mono-rt:   at Saalplan.RxTileSource..ctor (int) [0x00000] in /Users/rxDeveloper/Projects/rx.app.seatingmap/Xamarin.iOS/RxTileSource.cs:12
mono-rt:   at Saalplan.TileViewController.InitMapView () [0x00006] in /Users/rxDeveloper/Projects/rx.app.seatingmap/Xamarin.iOS/TileViewController.cs:24
mono-rt:   at Saalplan.TileViewController.ViewDidLoad () [0x00008] in /Users/rxDeveloper/Projects/rx.app.seatingmap/Xamarin.iOS/

The Question

What is the correct way of binding this combination of inheritance and protocol implementation?

Upvotes: 1

Views: 1313

Answers (3)

egfconnor
egfconnor

Reputation: 2647

For what it's worth for others coming across this. My issue was that my linkwith.cs file didn't contain LinkTarget.Simulator64. I was getting the error object xxx of class yyy does not implement methodSignatureForSelector: -- trouble ahead message.

Upvotes: 0

Felix Ruzzoli
Felix Ruzzoli

Reputation: 91

We got the bindings working now. The problem was our linkwith.cs file. Using the above bindings and the following linkwith.cs file worked:

[assembly: LinkWith ("libXMap.a", LinkTarget.ArmV7 | LinkTarget.ArmV7s | LinkTarget.Simulator, Frameworks = "CoreLocation QuartzCore UIKit Foundation CoreGraphics", LinkerFlags = "-lz -lsqlite3", ForceLoad = true, IsCxx = true)]

Upvotes: 1

Blueberry
Blueberry

Reputation: 2231

Have you had a look at the existing monotouch binding example? You can find it here:

https://github.com/mono/monotouch-bindings/tree/master/Route-Me

Upvotes: 0

Related Questions