-
Notifications
You must be signed in to change notification settings - Fork 4.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
Native AOT CLI Experience Improvements in .NET 8 #79570
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas Issue DetailsThe Native AOT CLI (SDK) experience has a lot of rough edges and room for improvement.
|
Sorry to bump this with a few people on it, but I'm interested in helping with this. I have a few projects I want to work on that depend on building native libraries from C# code, but the experience has been frustrating. I'm not very experienced with "compiler stuff", nor have I landed changes in .NET, but I'd love to learn way more about both, and this seems like a great opportunity to do so. If you've got time, please send some pointers for where work can be done on these. |
@xylobol The issues linked in there might be a good place to get started, but I'd love to make your experience better. Maybe you could try writing down what you wanted to and what you expected the experience to be, then the problems with it? Writing native libraries is a pretty new thing for the dotnet toolchain so I expect there are some rough edges, but don't have a good sense of what people will run into. |
I'm trying to get a "native" shared library that I can dynamically load from a C/C++ program running on Linux. The generation itself seems to be fine on the .NET side - I can inspect the compiled library and see my methods. I haven't been able to consume the library though - per #70277, there's a ton of extra things to link when building. A complete example using CMake would be very helpful. |
I got it working and prepared an example solution over at https://github.com/Xylobol/DotNet-NativeAOT-Library-Example. I'm likely going to add extra information on writing headers and calling from C/C++ later, maybe in addition to how to deal with static libraries. EDIT 12/24/22, a few minutes after posting: A source generator for header files would be killer |
A few more questions:
Merry Christmas or whatever you all may celebrate, and happy New Year! |
In the new Christmas tradition of answering my own questions: for any other explorers, use delegates for the first part of that last post! In the exporting lib: public static partial class Class1
{
// Callback function which is called from the unmanaged code
[UnmanagedCallersOnly]
private static void TestCallback()
{
Console.WriteLine("Hello from the test callback");
}
[UnmanagedCallersOnly(EntryPoint = "GetFunctionPointer", CallConvs = new[] { typeof(CallConvCdecl) })]
private static unsafe delegate* unmanaged<void> GetFunctionPointer()
{
return &TestCallback;
}
} In the program you're calling from, in this case also written in C#: public static partial class Class1
{
private delegate void TestDelegate();
[LibraryImport("whatever.dll", EntryPoint = "GetFunctionPointer")]
[UnmanagedCallConv(CallConvs = new Type[] { typeof(System.Runtime.CompilerServices.CallConvCdecl) })]
private static partial nint GetFunctionPointer();
private static readonly TestDelegate Delegate = Marshal.GetDelegateForFunctionPointer<TestDelegate>(GetFunctionPointer());
public static void RunTheFunction() => Delegate();
} A lot of this seems like documentation that assumes you already know what you're doing - I'd love to help with that, whether that's writing or just giving input to someone else who is. |
private static nint GetFunctionPointer()
{
var testDelegate = new TestDelegate(TestCallback);
return Marshal.GetFunctionPointerForDelegate(testDelegate);
} This method has "callback on collected delegate" bug that will cause it to crash intermittently. Marshal.GetFunctionPointerForDelegate documentation public static partial class Class1
{
private delegate void TestDelegate();
//Callback function which is called from the unmanaged code
[UnmanagedCallersOnly]
private static void TestCallback()
{
Console.WriteLine("Hello from the test callback");
}
[UnmanagedCallersOnly(EntryPoint = "GetFunctionPointer", CallConvs = new[] { typeof(CallConvCdecl) })]
public static unsafe delegate* unmanaged<void> GetFunctionPointerNative() => &TestCallback;
} Similarly, you can use function pointers for the calling code as well. |
Wow, that's really clean - thanks for showing me! I'll update my example soon. |
I pushed static library publishing to .NET 9. We don't currently have plans to encourage people to do static libraries. It will be more realistic if we do #83611 - that one avoids the issue of "you need to match the toolset that was used to compile the unmanaged parts of the runtime or bad things might happen". There's nothing else left here, so closing. |
The Native AOT CLI (SDK) experience has a lot of rough edges and room for improvement.
The text was updated successfully, but these errors were encountered: