{"id":3671,"date":"2013-03-26T15:48:33","date_gmt":"2013-03-26T22:48:33","guid":{"rendered":"http:\/\/blog.xamarin.com\/?p=3671"},"modified":"2019-07-03T10:11:42","modified_gmt":"2019-07-03T17:11:42","slug":"producing-better-bindings-4-signatures","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/producing-better-bindings-4-signatures\/","title":{"rendered":"Producing Better Bindings #4: Signatures"},"content":{"rendered":"<p>\t\t\t\tThis blog post is about producing better bindings of Objective-C libraries for <a href=\"http:\/\/xamarin.com\/monotouch\">Xamarin.iOS<\/a> and <a href=\"http:\/\/xamarin.com\/mac\">Xamarin.Mac<\/a>. Read the series <a href=\"\/producing-better-bindings-for-xamarin.ios-and-xamarin.mac\/\">introduction<\/a> to get a better idea why this is important and how it can save you time and headaches.<\/p>\n<p><strong>What can go wrong ?<\/strong><\/p>\n<p>Binding a selector using a correct <code>[Export(\"\")]<\/code> attribute is only half the job. The .NET method signature <strong>must<\/strong> match the one defined in Objective-C. Xamarin.iOS does some magic, like converting <code>string<\/code> and <code>NSString<\/code>, but you still need to be careful. The most common mistakes are:<\/p>\n<ul>\n<li><strong>signed\/unsigned types<\/strong>: this is often minor and you might want to <a href=\"https:\/\/github.com\/mono\/monotouch-bindings\/blob\/master\/cocos2d\/binding-test\/BindingSignatureTest.cs#L99\">disable the check<\/a> on some (or even all) of them. <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/12a7a7h3.aspx\">CLS compliance<\/a> means .NET developers prefer signed over unsigned integers (except for <code>byte<\/code>). Apple APIs often use unsigned integers when a number cannot be negative. For example:<\/li>\n<\/ul>\n<pre class=\"lang:objc\">\n@property (nonatomic, readwrite) NSUInteger loops;\n<\/pre>\n<pre class=\"lang:csharp decode:true\">\n[Export (&quot;loops&quot;)]\nint Loops { get; set; }\n\/\/ should be uint, easier (less casting) if an int\n<\/pre>\n<ul>\n<li><strong>wrong types<\/strong>: a common case is a missing <code>ref<\/code> when the Objective-C API requires a pointer to a value, not the value itself. For example:<\/li>\n<\/ul>\n<pre class=\"lang:objc\">\n-(void) sphericalRadius:(float*) r zenith:(float*) zenith azimuth:(float*) azimuth;\n<\/pre>\n<pre class=\"lang:csharp decode:true\">\n[Export (&quot;sphericalRadius:zenith:azimuth:&quot;)]\nvoid GetSphere (float radius, float zenith, float azimuth);\n\/\/ wrong, references to float (ref float) should have been used\n<\/pre>\n<ul>\n<li><strong>wrong size<\/strong>: this often happens on structures, but it can also occurs when a type name is misleading (e.g. <code>long<\/code> 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:<\/li>\n<\/ul>\n<pre class=\"lang:objc\">\n-(id) initWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue;\n<\/pre>\n<pre class=\"lang:csharp decode:true\">\n[Export (&quot;initWithDuration:red:green:blue:&quot;)]\nIntPtr Constructor (float duration, byte red, byte green, byte blue);\n\/\/ wrong, we're almost wired for bytes when seeing RGB but it does not have to be!\n<\/pre>\n<p><strong>What can we check for ?<\/strong><\/p>\n<p>Quite a lot. It&#8217;s possible to get an encoded signature for selectors. The earlier <code>loops<\/code> selector, for example, would return the &#8220;<code>I8@0:4<\/code>&#8221; string value.<\/p>\n<p>From it we can extract the return value (<code>I<\/code> an <code>unsigned int<\/code>) and all the parameters, e.g. self (<code>@<\/code>) and the selector (<code>:<\/code>) are always present and there are no other parameters since it&#8217;s a getter. We also get the size of the parameters, which can be compared to the size of the managed types used\u2014and they should <strong>always<\/strong> match!<\/p>\n<p>Using all of the above, we can test pretty closely if an Objective-C signature matches the defined .NET signature. Simple? Not quite.<\/p>\n<p>Objective-C encoding for structures is quite detailed. However, their internal names won&#8217;t match the one being used in your bindings. You&#8217;ll need to help the <a href=\"https:\/\/github.com\/mono\/maccore\/blob\/master\/tests\/bindings\/ApiSignatureTest.cs\">fixture<\/a> to map them by <a href=\"https:\/\/github.com\/mono\/monotouch-bindings\/blob\/master\/cocos2d\/binding-test\/BindingSignatureTest.cs#L66\">overriding<\/a> its <code>IsValidStruct<\/code> method.<\/p>\n<p><strong>Why is this important ?<\/strong><\/p>\n<p>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.<\/p>\n<p><strong>How to fix issues ?<\/strong><\/p>\n<p>Fixing the .NET signature to match it&#8217;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&#8217;s documentation and\/or it&#8217;s header files.<\/p>\n<p>One notable (and uncommon) exception is the use of a variable number of arguments (e.g. <code>var_list<\/code> in Objective-C, <code>params<\/code> in C#). They are not part of the encoded signature, so once confirmed you can skip them by <a href=\"https:\/\/github.com\/mono\/monotouch-bindings\/blob\/master\/cocos2d\/binding-test\/BindingSignatureTest.cs#L51\">overriding<\/a> the <code>Skip(Type,MethodInfo,string)<\/code> method.<\/p>\n<p>As discussed earlier, you might also want to override <code>Check(char,Type)<\/code> to skip the signed\/unsigned differences for integer types.<\/p>\n<p><strong>What&#8217;s missing ?<\/strong><\/p>\n<p>The encoded signature is not perfect. All <code>NSObject<\/code> parameters are encoded as &#8216;<code>@<\/code>&#8216; so we cannot detect if an <code>NSData<\/code> should have been used instead of <code>NSDate<\/code>. Since all objects are pointers, they all will be the same size (<code>IntPtr.Size<\/code>) so this will also not be noticed by the size check. Typos\/errors, even if less common, are still possible.<\/p>\n<p>This blog post concludes the five-part series on building better bindings for Xamarin.iOS and Xamarin.Mac. Thanks for reading!<\/p>\n<p><b>Read the rest of the series:<\/b><\/p>\n<ul>\n<li><a href=\"\/producing-better-bindings-for-xamarin.ios-and-xamarin.mac\/\">Introduction<\/a><\/li>\n<li><a href=\"\/producing-better-bindings-1-constructors\/\">Part 1: Constructors<\/a><\/li>\n<li><a href=\"\/producing-better-bindings-2-fields\/\">Part 2: Fields<\/a><\/li>\n<li><a href=\"\/producing-better-bindings-3-selectors\/\">Part 3: Selectors<\/a><\/li>\n<\/ul>\n<p><a href=\"http:\/\/forums.xamarin.com\/discussion\/2433\/producing-better-bindings\">Discuss this post on the Xamarin forums<\/a>\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This blog post is about producing better bindings of Objective-C libraries for Xamarin.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(&#8220;&#8221;)] attribute is only half the job. [&hellip;]<\/p>\n","protected":false},"author":5741,"featured_media":39167,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[303],"tags":[4],"class_list":["post-3671","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ios","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>This blog post is about producing better bindings of Objective-C libraries for Xamarin.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(&#8220;&#8221;)] attribute is only half the job. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/3671","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/5741"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=3671"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/3671\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=3671"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=3671"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=3671"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}