Skip to content
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

Swift Bindings - General questions #2743

Open
kusc-leica opened this issue Oct 31, 2024 · 3 comments
Open

Swift Bindings - General questions #2743

kusc-leica opened this issue Oct 31, 2024 · 3 comments
Assignees
Labels
area-SwiftBindings Swift bindings for .NET

Comments

@kusc-leica
Copy link

Hey there.

We are currently struggling a bit with the support of Swift in MAUI. We have a library which doesn't expose a ObjectiveC interface but we are in dire need of a binding library for a 3rd party product. After failing to use other tools I stumbled over the feature/swift-bindings branch in this repository and it kind-a looks promising.

As Microsoft has not really published yet any details on Swift interopability support but there seem to be a lot ongoing in development:

I understand the "experimental" nature of the ongoing development but still would have following questions and inputs:

  1. It seems the binding generator currently expects a dylib to be sitting beside the .abi.json, in the Cocoapod we wanna use, there is no dylib in the package. (Notificare, Cocoapod). I wonder if this is currently just a simplification or there is a design problem there. I saw that the dylib is only needed in some special scenario but still it is required to exist.
  2. Despite net9.0 being close, there still seem to be items shifted to net10.0. This raises the question to me: Assuming I manage to get some reasonable bindings generated, should the output already work in net8.0? If yes, I could maybe also just fix and adjust manually the bindings to the expected code structure. Unfortunately there are on guides on how you could do manually what the generator is trying to do.

Any help is highly appreciated so we could create some wrapper for the iOS library we need.

@kotlarmilos kotlarmilos added the area-SwiftBindings Swift bindings for .NET label Oct 31, 2024
@jkurdek jkurdek self-assigned this Nov 4, 2024
@jkurdek
Copy link
Member

jkurdek commented Nov 4, 2024

Hello @kusc-leica,

Thanks for reaching out, I'm happy to discuss your usage scenario!

Would you mind sharing some more details about your particular use case? It would allow us to offer you better guidance. What version of .NET do you target? Is it .NET 9 or .NET 8? Also, do you need to use some particular API from the library you shared, or you need to wrap all of the public API surface of the said library?

About your dylib question - the library which you want to use does have dylibs. They reside in .framework subdirectories for the given platform. So e.g. the dylib for NotificareAssetsKit can be found under Notificare/NotificareAssetsKit.xcframework/ios-arm64/NotificareAssetsKit.framework as NotificareAssetsKit. It does lack the .dyilb extension but it is still a valid dylib

@kusc-leica
Copy link
Author

Would you mind sharing some more details about your particular use case?

Sure! Basically the usecase is to wrap a iOS Swift Cocoapod library for usage in .net MAUI net8.0 (net9.0 might still be in the acceptable timeframe though). I think the usecases might span quite the typical needs of using a SDK from a 3rd party vendor:

  1. Calling functions and accessing properties/members of
  2. Implementing protocols/interfaces in .net classes to be able to pass them down to Swift (in callback scenarios):

There might be some special Swift constructs I am simply not aware of but generally we are just interested into "using" the library. Typical usage of this particular library looks like this:

https://docs.notifica.re/sdk/v4/ios/implementation/register/
https://docs.notifica.re/sdk/v4/ios/implementation/push/

I fear the implementatoin of protocols in .net objects might be the most problematic scenario while other bits like structs and class methods should be comparably easy.

Also, do you need to use some particular API from the library you shared, or you need to wrap all of the public API surface of the said library?

While temporarily we might be able to limit ourselves to only certain areas we really use, but eventually the idea would be to wrap the whole public API surface.

About your dylib question - the library which you want to use does have dylibs. They reside in .framework subdirectories for the given platform. So e.g. the dylib for NotificareAssetsKit can be found under Notificare/NotificareAssetsKit.xcframework/ios-arm64/NotificareAssetsKit.framework as NotificareAssetsKit. It does lack the .dyilb extension but it is still a valid dylib

Seems the assumption I a had was correct that this is currently just a "simplification" in the code. The code currently expects a .dylib file and there is no way of configuring things when you pass the .abi.json via --swiftabi.

dylib = $"{Path.GetDirectoryName(path)}/lib{Path.GetFileName(path).Replace(".abi.json", "")}.dylib";

@jkurdek
Copy link
Member

jkurdek commented Nov 6, 2024

Thanks for providing all the details!

net8.0 (net9.0 might still be in the acceptable timeframe though).

As you have already seen we shipped a lot of .NET runtime support for Swift in .NET 9. Those changes enable to call Swift in far more natural way. The story is not complete yet, but the current feature set should allow you to bind many Swift constructs. You can see an example of using those features to bind Apple CryptoKit here:

#2704

.Net 8 version for comparison (it required considerable amount of custom swift glue code):
dotnet/runtime@72ac50c#diff-ef8332a944e6f162e2443a946e87ec8cf561b2b5a7535ccdd61a5d923dd5f145R20


The tooling on feature/swift-bindings branch relies on those .NET 9 runtime bits to generate C# code. The generated code will be highly incompatible with .NET 8.

That said, currently the tooling is in experimental phase. It should generate bindings for some constructs (e.g. structs, simple methods), but it will fail on others (e.g. classes). Inspecting the test directory would give you the most up-to-date picture of the current support:
https://github.com/dotnet/runtimelab/tree/feature/swift-bindings/src/Swift.Bindings/tests

So, running the tooling might give you something to start with, but majority of the work will be writing bindings by hand. At the moment, looking at your use case, this means classes, extensions, protocols and parts of enums. Some ideas how to do so might be found here:
https://github.com/dotnet/runtimelab/tree/feature/swift-bindings/src/docs

Also, in order to use the tooling (or .NET 9 Swift support in general) you need to ensure that the library is built in library-evolution-mode https://www.swift.org/blog/library-evolution/. Library evolution mode is the only stable ABI story for Swift so all the .NET runtime support was designed with its being enabled in mind.

Should you decide to go down this path, we will be happy to discuss any rough edges you will find on the way.

Seems the assumption I a had was correct that this is currently just a "simplification" in the code. The code currently expects a .dylib file and there is no way of configuring things when you pass the .abi.json via --swiftabi.

Right, thanks for pointing this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-SwiftBindings Swift bindings for .NET
Projects
None yet
Development

No branches or pull requests

3 participants