[Mono-osx] MonoMac parser.cs
Miguel de Icaza
miguel at novell.com
Tue Apr 20 10:03:36 EDT 2010
Hello Duane,
I have taken parser.cs and extended it to handle categories. To start I
> tested parsing NSArray.h. This produced NSArray.cs and NSMutableArray.cs.
> I have "full" bindings for these obj-c classes.
>
We do not currently support a mapping to categories as they do not really
have a counter part in C#.
They are *similar* to interfaces, but they can be interfaces with optional
components so there is no direct mapping to them.
For the delegate pattern we settled on classes that have been labeled as
"Models" (read more about that on our binding page).
NSMutableArray: http://monobin.com/__m335d328c
> NSArray: http://monobin.com/__m36c66b6e
Nice. For the particular case of Foundation, we have taken an approach to
only bind what is actually *required* as opposed to binding everything.
Many bits from Foundation make sense for Objective-C programmers as they are
dealing with a low-level language and are redundant with C#.
In the particular case of NSArray and NSMutableArray our runtime has been
extended to natively convert NSArrays to C# arrays and back so the only code
that we bound is the required interop code for NSArray.
So we suggest to work instead on the AppKit bindings.
However not all the bindings generated are valid. For example I do not know
> how to generate a binding for this selector (note I do not use this
> selector, just an example):
> - (void)sortUsingFunction:(NSInteger (*)(id, id, void *))compare
> context:(void *)context;
>
Correct, the parser does the heavy lifting, but requires human intervention
to fix the output.
>
> Then comes the question of constructors. Take these two (the 2nd is not
> really a constructor I know) from NSMutableArray for example:
> + (id)arrayWithCapacity:(NSUInteger)numItems;
> - (id)initWithCapacity:(NSUInteger)numItems;
>
> My parser exposes these as:
>
> [Static]
> [Export ("arrayWithCapacity:")]
> IntPtr ArrayWithCapacity (uint numItems);
>
> [Export ("initWithCapacity:")]
> IntPtr InitWithCapacity (uint numItems);
>
This is a great question.
Factory methods should be declared as static methods, and we *typically* use
the FromXXXX or CreateXXX naming pattern for them, so the above would look
like this:
[Static, Export ("arrayWithCapacity:")]
NSArray CreateArray (int items);
Notice that I took the liberty of changing the uint to int because that
makes the method CLS compliant.
In this case it is a debatable change as there could be arrays with more
than 2 gig elements, but in many other places in the API this is not the
case, uint has been used to get an extra bit that is not required.
So how can we support the extra 2 gigs of elements while still allowing
other languages the most common use case? We keep the signature as it was
originally produced, and introduce a new overload:
[Static, Export ("arrayWithCapacity:")]
NSArray CreateArray (uint items);
And then on a helper class in Foundation/NSArray.cs we would do:
partial class NSArray {
static NSArray CreateArray (int items){
if (items < 0) throw new ArgumentException ();
return CreateArray ((uint) items);
}
}
Now to the second question:
First I do not think returning an IntPtr is correct. It should return
> NSMutableArray. But IntPtr follows what was started with MT. Returning an
> IntPtr will require calling GetNSObject which seems cumbersome. Unless I'm
> missing something.
>
In the specific case of *constructors* the binding generator recognizes the
pattern:
IntPtr Constructor (ARGS)
As being the constructor for the class. This is required because
constructors generate different code than regular method bindings.
So you will see in all of our APIs that we expose that pattern, but that
this is never translated into an actual exposed IntPtr, it is always
translated into the correct method name.
Miguel.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-osx/attachments/20100420/c220c8aa/attachment-0001.html
More information about the Mono-osx
mailing list