Monobjc, as a bridge, allows two differents runtimes to communicate with each others. As they have their particularities, the bridge uses the best of both.
The Objective-C runtime provides everything to inspect and alter it. It is possible by a wide range of funtions, as described in the Objective-C Runtime Reference guide.
The Monobjc bridge uses these features:
- to load shared library or framework bundles
- to send messages to existing Objective-C classes or instances
- to access instance variables of existing Objective-C instances
- to inject new classes into the Objective-C runtime
Most of the work is done through the P/Invoke technology described below.
The .NET runtime
The .NET runtime (on Mac OS X, the Mono runtime) provides a CLR (Common Language Runtime) compliant with the .NET specifications. One of the most useful feature of the .NET runtime is the ability to make native calls through the P/Invoke (short for Platform Invoke), through the use of declared attributes.
A P/Invoke call is basically described by :
- the signature of the method (parameters and return types)
- the shared library where the native function is found
- the function name mapping if any
- the marshalling options for the parameters
No extra code is needed beyond the annotated signature. The .NET runtime will then do all the necessary library loading and linking to make the function available.
For example, the NXGetLocalArchInfo function is declared as follow :
extern const NXArchInfo *NXGetLocalArchInfo(void);
This function can be mapped in .NET like this :
[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")] public static extern IntPtr NXGetLocalArchInfo();
The NXGetLocalArchInfo is now callable from any .NET code, just as a standard .NET method.
For more details about the P/Invoke technology, see this introduction paper.
In the following pages, you will see how the Monobjc bridge makes an heavy use of the P/Invoke calls in order to coordinate the Objective-C runtime from the .NET runtime.