-
Notifications
You must be signed in to change notification settings - Fork 507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invoking async swift code in an iOS binding library is crashing with an objective C encoding error #18562
Comments
Hello @jerrgreen sorry for the late response I was able to repro with the provided steps, would you be able to share with us the Swift library source? Thanks! |
Hi @jerrgreen. We have added the "need-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time. |
The library from the example is a pretty straightforward class class TestClass {
func DebugLog(message: String) -> String {
print(message)
return message
}
func DebugLog2(message: String) async -> String {
do {
try await Task.sleep(nanoseconds: 1_000_000_000)
} catch {}
print(message);
return message;
}
} |
It seems to work on real device though only simulator crash |
Please consider setting it as high priority issue that needs to be solved asap otherwise many important iOS API's could not be properly bound (at least for simulator..) - like StoreKit2 which makes development very difficult (simulator builds becomes unusable). Some of StoreKit2 API should be mapped due to the App Store guideliness (like give button and call manage subscriptions whenever user deletes account) To reproduce the issue please install following package:
On device:
On simulator:
You can get problematic .xcframework, swift project, xamarin bindings projects here: https://github.com/thefex/Xamarin.iOS.StoreKit2Sample |
My experience is not limited to the simulator, I am seeing these crashes on real devices |
Do you use xcframework? Or maybe the issue is more broad but in my case works..? I am using Xamarin Native (not MAUI) though without .NET 6 |
Yes, we're using xcframeworks for our swift integration |
I can reproduce this with the provided sample. |
The problem is that Swift seems to produce Objective-C code that doesn't conform to the spec. Using NSMethodSignature in an Xcode project also complains:
|
So this seems to be a bug in XCode / obj-c / swift compiler ? Are there any known workaround for such problems? |
I don't really think it's a bug. They just changed stuff and never bothered to update the documentation/spec. |
Hm... okey, can it be solved on Xamarin level though? Any tips how developer can still safely use those async swift methods in Xamarin.iOS? |
If we can figure out the format they're using, yes - so I asked on StackOverflow: https://stackoverflow.com/questions/76827926/whats-the-format-for-objc-method-description-types-for-swift-blocks
Try adding the following to your csproj: <PropertyGroup>
<MtouchExtraArgs>--require-pinvoke-wrappers=true</MtouchExtraArgs>
</PropertyGroup> |
Thanks. Do traditional non-async closure blocks (like regular handlers) can be parsed normally and there are no issues? Sorry, if that does not make much sense but I am not an expert in those internals |
As long as the method signature string doesn't contain |
Hm... then I think the problem are more widespread than that.. and probably not solvable 'the easy way' Those extended swift types seems to be not parsable in obj-c, and obj-c runtime somehow finds 'swift compiler generated method thunk' that calls swift method taking care about all of the internal representation.. I just wonder.. maybe the easy workaround would be creating additional obj-c methods that calls those swift obj-c compatibile methods and bind only those obj-c methods? EDIT: EDIT2: (base) Przemysaws-MacBook-Pro-2:ios-arm64_x86_64-simulator przemyslawraciborski$ nm -g StoreKit2.framework/StoreKit2 One method seems to have two function ptrs (though one is marked as U -> linked outside of .framework which I dont get completely). |
Good news, I added this to the property and can confirm that the async code can be invoked, so this does look like a valid work around for the issue. |
@rolfbjarne Are there any docs for --require pinvoke? What it exactly does? |
For every P/Invoke to the Objective-C messaging functions ( The downside is that the app will be bigger due to the extra code. The upside is that the code will likely be slightly faster (the default is to call a generic wrapper function that works for all P/Invokes - this is slightly slower, but smaller - and this is where the bug is, in this generic wrapper functoin we need to figure out the signature of the target native method we need to call, and that's where we run into what the Swift compiler does). |
Does "--require-pinvoke-wrappers=true" work on a "net7.0-ios" bindings library? I'm having the same issue of apps crashing when calling async Swift bindings. The only thing that is logged is: The --require-pinvoke-wrappers=true doesn't seem to have an impact. This page on migrating projects seems to indicate that some MtouchExtraArgs are no longer applicable: https://learn.microsoft.com/en-us/dotnet/maui/migration/apple-projects |
You need to add it to the executable project, not the bindings project. If that doesn't work, please attach a binlog for a build with the problem. |
Sorry if I'm being dumb, but when I enable "--require-pinvoke-wrappers=true" on the executable project, I get an exception on launch (see below). I suspect this is an unrelated issue.
|
I put together a small sample. It's a .Net7 iOS app and binding project. The binding project wraps a simple Xcode framework with a sync and async method that just outputs to console (also in the zip). The sync method works fine from the C# testapp, but the async method crashes (when I don't have pinvoke wrappers enabled) with the error logged in iOS as: I can't enabled pinvoke-wrappers due to the crash on launch in my previous comment. There are bin logs for both the binding library build, as well as the TestApp, in the respective project folders. |
@marcb777 I can reproduce the problem, but it works if you add this to the project as well: <PropertyGroup>
<Registrar>static</Registrar>
</PropertyGroup> |
Ahh - thanks so much @rolfbjarne . That appears to have resolved the issue I was facing. To be clear, is that needed on the bindings project, the app project, or both? |
Just the app project. |
Stackoverflow came to the rescue and found this: It looks like it's exactly what we need to implement this. |
Redirected here from MAUI
I am trying to integrate an iOS binding library with a swift library that uses asynchronous methods. When I hit a method that is synchronous, the method executes successfully. When I try to invoke any asynchronous method, the app crashes. The last exception that I see in the logs is "Microsoft.iOS: Unsupported type encoding: "NSString"16@?<v@?@"NSString">24".
Referencing the Binding details for Xamarin,, I'd expect this to be fully supported, but I cannot find a way past this error.
I've been able to reproduce this on both the latest versions of dotnet 6 and dotnet 7.
Steps to Reproduce
Expected Behavior
The swift method executes successfully
Actual Behavior
The application crashes
Environment
Version information
Build Logs
Logs
Example Project (If Possible)
Sample Repo
The text was updated successfully, but these errors were encountered: