Bug 30766 - Native compiling no longer works with some native libraries
Summary: Native compiling no longer works with some native libraries
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 8.10
Hardware: All All
: --- normal
Target Milestone: 8.13 (C6 alpha)
Assignee: Rolf Bjarne Kvinge [MSFT]
URL:
: 31425 ()
Depends on:
Blocks:
 
Reported: 2015-06-04 03:50 UTC by Fabien Molinet
Modified: 2015-08-12 04:55 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Fabien Molinet 2015-06-04 03:50:30 UTC
Hi,

Native compiling using Xamarin.iOS10 no longer works as expected with some native libraries (like PSPDFKit).
Issues are:
- when iOS Delegates are used then we get some errors like [NSProxy doesNotRecognizeSelector:pdfViewController:shouldScrollToPage:]
- subclassing native classes from native lib works randomly

This issue has been confirmed by Alex Soto in PSPDFKit bugtracker.

Please note that downgrading to Xamarin.iOS9 is not an option for us. Xamarin.iOS9 has other issues, which prevents us from building, and these issues were fixed in 8.10.

Can we please have an urgent fix? This is a major concern for us since we can't make anymore builds.

Cheers,
Fabien
Comment 1 Alex Soto [MSFT] 2015-06-04 04:04:05 UTC
Attaching a test case 

https://www.dropbox.com/s/hb714b4i6zhxy5x/ProtocolBug.zip?dl=0

I debugged the native library and in ObjC it does work, also tried getting the protocol method list count by using protocol_copyMethodDescriptionList and it does what I expect in simulator but just breaks in device if any *Delegate object is being subclassed or interface implemented. 

The funny thing is that his bug only happens if you try to use any *Delegate from the assembly as an interface directly or as a inherited class and overriding its methods. If you delete all of the *Delegate subclasses the app just works.
Comment 2 Alex Soto [MSFT] 2015-06-04 04:05:21 UTC
This bug does not happen in X.I 8.8 or 8.9, it broke in X.I 8.10
Comment 3 Peter Steinberger 2015-06-04 04:46:06 UTC
(PSPDFKit author here)

While trying to work around this with Alex we also tried calling protocol_getMethodDescription directly, which leads to a hang right away (ritical: Stacktrace: 2015-06-04 03:43:30.128 ProtocolBug[78874:7515963] critical:   at <unknown> <0xffffffff>)

The protocol_copyMethodDescriptionList method at least fails without hanging.
Comment 4 Rolf Bjarne Kvinge [MSFT] 2015-06-04 05:45:23 UTC
@Peter, are you using NSProxy in PSPDFKit (and if so, what are you using it for)?
Comment 5 Peter Steinberger 2015-06-04 05:59:12 UTC
Rolf, yes we are - basically in most instances where optional protocols are used. This reduces calls to one line, simulating a language feature that Swift now has natively.

It's open source: https://github.com/steipete/PSTDelegateProxy

The one problematic case is when the internal delegate is already nilled out - objectivec message forwarding is triggered and we need to get a correct method signature so that forwardInvocation: is called.

In the delegate proxy I use the runtime to query the protocol info: https://github.com/steipete/PSTDelegateProxy/blob/master/PSTDelegateProxy.m#L115

This works great - just now under Xamarin protocol_copyMethodDescriptionList suddently fails (returning 0 methods both for optional and required), so we return methodSignatureForSelector, which then triggers an selector not found exception instead of calling our custom forwardInvocation: that was supposed to swallow just that. (The invocation can't be created without a matching method signature - and we can't just create one at random based on the selector alone, that one doesn't contain type info)
Comment 6 Rolf Bjarne Kvinge [MSFT] 2015-06-04 13:31:33 UTC
There's a workaround: add [Abstract] to all the members of the protocol in the api definition, and implement those in consumers of the protocol (it looks like those implementations can just throw a NotImplementedException).
Comment 7 Peter Steinberger 2015-06-04 15:11:48 UTC
Hmmm. The bug appears both for wrapped protocols and internal ones that are not exposed at all in C#... but fail runtime calls as soon as things are linked with Xamarin. I'm not sure how adding [Abstract]  could fix that?
Comment 8 Rolf Bjarne Kvinge [MSFT] 2015-06-05 04:14:12 UTC
@Peter, the test case only shows a problem with PSPDFViewControllerDelegate, and the bug I found would not affect any protocol not bound by the binding library, so if you have problems with internal protocols as well there's another bug too.

For the test project Alex posted, this version of PSPDFViewControllerDelegate works: https://gist.github.com/rolfbjarne/58dd9f9c6d1da40b8042

BTW: the bug can be reproduced in the simulator by adding "--registrar:static" to the additional mtouch arguments.

What happens is this:
* The static registrar re-creates the protocol definition in Objective-C (since we don't have access to nor use the headers), and doesn't include optional members.
* Contrary to what (C-related) intuition says, protocols in headers do not work like other header declarations: protocols are embedded in the binary of every file that uses the protocol, and since the protocol the static registrar generates and the one actually defined in the Objective-C header are different, the runtime code that depends on the specific protocol being correct, ends up finding the wrong one generated by the static registrar (and fails).

Adding [Abstract] to the protocol members in the api definition makes the re-created protocol definition more similar to the original header (enough to make the test project work at least).
Comment 9 Rolf Bjarne Kvinge [MSFT] 2015-06-30 03:36:46 UTC
*** Bug 31425 has been marked as a duplicate of this bug. ***
Comment 10 Rolf Bjarne Kvinge [MSFT] 2015-08-12 04:55:20 UTC
Fixed.

maccore/master: 4ce8fd282bcdbd9c837b936b9d9b67a5b72081c0