-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
DllImport with .a file for iOS in MAUI #12675
Comments
I believe your issue is more of a question of the MaciOS SDK and not an MAUI UI Framework issue, it may be a better fit over at https://github.com/xamarin/xamarin-macios. You may want to follow the Reference Native Library section in the docs (https://learn.microsoft.com/en-us/xamarin/ios/platform/native-interop), which explains where to put the library and how to link to it. While it's intended for Xamarin.iOS, it should also apply to dotnet iOS / MAUI apps. @rolfbjarne @dalexsoto Are there other ways to help this user? |
Use This is documented here: https://www.mono-project.com/docs/advanced/pinvoke/
Don't do this. Use a <ItemGroup>
<NativeReference Include="path/to/fat.a" Kind="Static" />
</ItemGroup>
You're not supposed to see any .a files in the final app, the .a file is linked into the main executable. |
@rolfbjarne Thanks for the info! We'll try and let you know if it works or not. Meanwhile, I wonder how to combine all these facts into single cross-platform codebase. Well, for desktop developement we use dynamic native libraries via Also about <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)Melanchall_DryWetMidi_Native32.dll">
<Visible>false</Visible>
<Link>Melanchall_DryWetMidi_Native32.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Melanchall_DryWetMidi_Native64.dll">
<Visible>false</Visible>
<Link>Melanchall_DryWetMidi_Native64.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)Melanchall_DryWetMidi_Native64.dylib">
<Visible>false</Visible>
<Link>Melanchall_DryWetMidi_Native64.dylib</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project> Will it be OK if I add |
Hi there, +++ I am the user who works with melanchall together on this issue. To clarify for others who stumble upon this kind of issue: the static library Despite it’s the wrong approach ;-) as rolfbjarne said – but just to make this comprehensible for other situations. Its possible to verify this in the local build output folder for the iOS simulator target on the windows machine : +++ Following rolfbjarne’s instructions, I placed the <ItemGroup>
<NativeReference Include="fat.a" Kind="Static" />
</ItemGroup> [DllImport("__Internal")]
private static extern int Foo(); Which takes VS out of “visual sync” in the File Properties toolbar window by the way, because it does not recognizes this “file directive” – it shows And it works : the code executes with no exception and returns the expected result (which is 234 by the way, as it is executed on a 64-bit Arm iOS simulator). Another 2 things (beside File Properties tool window “out of visual sync”) that the .NET MAUI team should take a look at :
... but it works ! ;-) ! Cheers |
That's weird... the easiest way to debug this is usually to get a binary build log and then search for the library (
For NuGets we'll automatically detect any *.a files from the If you create a |
Hi @melanchall. We have added the "s/needs-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. |
@rolfbjarne Thanks! I have a couple of questions. Here is my csproj file – Melanchall.DryWetMidi.csproj. Can I just put such an element into <None Include="Melanchall_DryWetMidi_Native64.a">
<PackagePath>runtimes\_rid_\native\</PackagePath>
<Pack>true</Pack>
</None> ? So I mean can I get rid of special binding library project ( And I unfortunately didn't get an answer on the question regarding library name in [DllImport(LibraryName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] For desktop applications such attribute works: [DllImport("Melanchall_DryWetMidi_Native64", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] looking for Melanchall_DryWetMidi_Native64.dll on Windows, Melanchall_DryWetMidi_Native64.dylib on on macOS and Melanchall_DryWetMidi_Native64.so on Linux. But as you said, for iOS we need such declaration of the attribute: [DllImport("__Internal", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] So we need to determine in runtime that we are on iOS and switch library name in Sorry for probably stupid questions, but it's really hard to find a complete guide on how to implement cross-platform .NET application with native binaries. Thanks, |
You may be able to do this: #if IOS
[DllImport("__Internal", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
#else
[DllImport("Melanchall_DryWetMidi_Native64", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
#endif
private static extern int Foo(); Or following your code: #if IOS
const string libraryName = "__Internal";
#else
const string libraryName = "Melanchall_DryWetMidi_Native64";
#endif
[DllImport(libraryName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
private static extern int Foo(); @rolfbjarne may need to confirm the csproj things, but this feels correct: <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<None Include="Melanchall_DryWetMidi_Native64.dll">
<PackagePath>runtimes\win10-x64\native\</PackagePath>
<Pack>true</Pack>
</None>
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<NativeReference Include="Melanchall_DryWetMidi_Native64.a" Kind="Static" />
</ItemGroup> If I understand all the comments, we have separate assemblies for each TFM, so we can write different code and can use the |
@mattleibow that looks good, but I believe you'll also have to add |
So I am also trying something similar and have followed @rolfbjarne's advice in terms of using "__Internal" for the DLL import library name and also using NativeReference import inside the .csproj file for importing my 'library.a' file. However I am getting compile errors for every method that I have declared in the likes of: From what I understand I am importing correctly in Visual Studio - however the 'library.a' might not be build correctly (I am building it myself on my remote mac using cmake and XCode). Is there a good way to troubleshoot this kind of error, like exploring the 'library.a' file and seeing if the methods are indeed exposed or somehow verify that the library is indeed valid? |
Nevermind I just figured it out. Actually found a post on MSDN forums link where I think @rolfbjarne also provided the answer 🥇 In short I ran |
@mattleibow @rolfbjarne Thank you! I have some comments. Probably this is wrong: <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<None Include="Melanchall_DryWetMidi_Native64.dll">
<PackagePath>runtimes\win10-x64\native\</PackagePath>
<Pack>true</Pack>
</None>
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<NativeReference Include="Melanchall_DryWetMidi_Native64.a" Kind="Static" />
</ItemGroup> I think you've mixed up fragments for csproj of the library and csproj for an end user project. Currently in my csproj (csproj of the library) I have: <ItemGroup Label="Native">
<None Include="Melanchall_DryWetMidi_Native32.dll">
<PackagePath>build\</PackagePath>
<Pack>true</Pack>
</None>
<None Include="Melanchall_DryWetMidi_Native64.dll">
<PackagePath>build\</PackagePath>
<Pack>true</Pack>
</None>
<None Include="Melanchall_DryWetMidi_Native64.dylib">
<PackagePath>build\</PackagePath>
<Pack>true</Pack>
</None>
<None Include="Melanchall.DryWetMidi.targets">
<PackagePath>build\</PackagePath>
<Pack>true</Pack>
</None>
</ItemGroup> This <None Include="Melanchall_DryWetMidi_Native64.a">
<PackagePath>runtimes\_rid_\native\</PackagePath>
<Pack>true</Pack>
</None> (where rid is an appropriate iOS RID). Also from this comment – #12675 (comment) – I've made a conclusion that
@rolfbjarne Am I right? Or the comment of @mattleibow is correct and I need to include |
@rolfbjarne that +++ Another question : where is the build output directory for the project on the Mac build host, as its not under the typicall Xcode path ( Are the some docs about the build mechanics for .NET MAUI already existant somewhere, as the project system has changed from its Xamarin iOS roots? thanks & cheers |
Hey all! I see a lot is going on here which is great! From what I gather the initial issue seems fixed so I will be closing this for now. If I misunderstood, please open a discussion (it looks more like a "how-to" discussion at this point?) or issue on the https://github.com/xamarin/xamarin-macios repo which seems more suitable in this case. Thanks everyone! |
I'm trying to add iOS support in my library. In the library I use functions from native binaries via
DllImport
attributes. So for example:It works without any problems on Windows (via libraryname.dll) and macOS (via libraryname.dylib). From what I've learned from the discussion with the library user, we need .a file for iOS. The user has prepared a simple test MAUI solution: Testify.zip. In the MainPage.xaml.cs we have this declaration:
fat.a has been built from this simple C code:
Here you can get the file: fat.zip. The build process:
Also the file is put to the Resources/Raw folder with
Copy to Output Directory
set toCopy always
. We see the file in proper place in the built package on a target device or iOS simulator. But callingFoo
we get the exception in runtime: System.DllNotFoundException: fat.a. Please see this comment for more details.So the question is how to use
DllImport
with native binaries for iOS in a MAUI project? Is it possible at all?The text was updated successfully, but these errors were encountered: