Xamarin.ios 绑定Objective-C libraries中容易出现的问题

This blog post is about producing better bindings of Objective-C libraries forXamarin.iOS and Xamarin.Mac . Read the series introduction to get a better idea why this is important and how it can save you time and headaches.

What can go wrong ?

Binding a selector using a correct [Export("")] attribute is only half the job. The .NET method signature must match the one defined in Objective-C. Xamarin.iOS does some magic, like converting string and NSString , but you still need to be careful. The most common mistakes are:

  • signed/unsigned types : this is often minor and you might want to disable the check on some (or even all) of them. CLS compliance means .NET developers prefer signed over unsigned integers (except for byte ). Apple APIs often use unsigned integers when a number cannot be negative. For example:
@property (nonatomic, readwrite) NSUInteger loops;
[Export ("loops")]
int Loops { get; set; }
// should be uint, easier (less casting) if an int
  • wrong types : a common case is a missing ref when the Objective-C API requires a pointer to a value, not the value itself. For example:
-(void) sphericalRadius:(float*) r zenith:(float*) zenith azimuth:(float*) azimuth;
[Export ("sphericalRadius:zenith:azimuth:")]
void GetSphere (float radius, float zenith, float azimuth);
// wrong, references to float (ref float) should have been used
  • wrong size : this often happens on structures, but it can also occurs when a type name is misleading (e.g. long is 32 bits in Objective-C, at least for 32bits archs like i386 and ARM, while it is 64 bits on .NET) or when common usage differs, as in this case:
-(id) initWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue;
[Export ("initWithDuration:red:green:blue:")]
IntPtr Constructor (float duration, byte red, byte green, byte blue);
// wrong, we're almost wired for bytes when seeing RGB but it does not have to be!

What can we check for ?

Quite a lot. It’s possible to get an encoded signature for selectors. The earlierloops selector, for example, would return the “ I8@0:4 ” string value.

From it we can extract the return value ( I an unsigned int ) and all the parameters, e.g. self ( @ ) and the selector ( : ) are always present and there are no other parameters since it’s a getter. We also get the size of the parameters, which can be compared to the size of the managed types used—and they should alwaysmatch!

Using all of the above, we can test pretty closely if an Objective-C signature matches the defined .NET signature. Simple? Not quite.

Objective-C encoding for structures is quite detailed. However, their internal names won’t match the one being used in your bindings. You’ll need to help the fixture to map them by overriding its IsValidStruct method.

Why is this important ?

Signature mistakes are dangerous. Some APIs might (appear to) work, others will crash immediately (bad) or the crash will occur later (worse) because they will mess up the stack and cause memory corruption. Debugging such issues can be very time consuming, so your time is well invested in using this fixture.

How to fix issues ?

Fixing the .NET signature to match it’s Objectice-C peer is the most common case. The failure will tell you which parameter (or the return value) looks wrong. You have to confirm/fix this using the library’s documentation and/or it’s header files.

One notable (and uncommon) exception is the use of a variable number of arguments (e.g. var_list in Objective-C, params in C#). They are not part of the encoded signature, so once confirmed you can skip them by overriding theSkip(Type,MethodInfo,string) method.

As discussed earlier, you might also want to override Check(char,Type) to skip the signed/unsigned differences for integer types.

What’s missing ?

The encoded signature is not perfect. All NSObject parameters are encoded as ‘@ ‘ so we cannot detect if an NSData should have been used instead of NSDate . Since all objects are pointers, they all will be the same size ( IntPtr.Size ) so this will also not be noticed by the size check. Typos/errors, even if less common, are still possible.

This blog post concludes the five-part series on building better bindings for Xamarin.iOS and Xamarin.Mac. Thanks for reading!




原文链接:

http://blog.xamarin.com/producing-better-bindings-4-signatures/?utm_source=tuicool

http://www.tuicool.com/articles/6VvE73

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值