Setup:
# On Ubuntu x64, using .NET 7 preview 5
$ dotnet new classlib -n lib1 && cd lib1
$ cat > Class1.cs <<EOF
using System;
using System.Runtime.InteropServices;
namespace lib1;
public class EntrypointWithCallback
{
[UnmanagedCallersOnly(EntryPoint = "myadd")]
public unsafe static int Add(int a, int b, delegate* unmanaged<int, int, int, int> callback)
{
Console.WriteLine("Hello from C# Add!");
return callback (a, b, a + b);
}
}
EOF
$ dotnet publish -c Release --use-current-runtime -o dist -p:PublishAot=true -p:NativeLib=static
$ cat > test.c <<EOF
#include<stdio.h>
typedef int(*callback_iii)(int, int, int);
extern int myadd(int, int, callback_iii);
int foo(int x, int y, int sum)
{
printf("Hello from C callback!\n");
return sum;
}
int main()
{
printf("sum is: %d\n", myadd(1, 2, &foo));
return 0;
}
EOF
Compiling test.c with dist/lib1.a is not straightforward. I figured it out using hints from -p:NativeLib=shared -v:diag. This is how the working command looks like:
$ cc test.c dist/lib1.a \
~/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/7.0.0-preview.5.22301.12/sdk/libbootstrapperdll.a \
~/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/7.0.0-preview.5.22301.12/sdk/libRuntime.WorkstationGC.a \
~/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/7.0.0-preview.5.22301.12/framework/libSystem.Native.a \
~/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/7.0.0-preview.5.22301.12/framework/libSystem.Globalization.Native.a \
~/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/7.0.0-preview.5.22301.12/framework/libSystem.IO.Compression.Native.a \
~/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/7.0.0-preview.5.22301.12/framework/libSystem.Net.Security.Native.a \
~/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/7.0.0-preview.5.22301.12/framework/libSystem.Security.Cryptography.Native.OpenSsl.a \
-Wall -pthread -lstdc++ -ldl -lm -Wl,--require-defined,NativeAOT_StaticInitialization
$ ./a.out
Hello from C# Add!
Hello from C callback!
sum is: 3
I think we should copy all the required .a files into the publish directory and create a helper script (.sh) for the user.
Setup:
Compiling
test.cwithdist/lib1.ais not straightforward. I figured it out using hints from-p:NativeLib=shared -v:diag. This is how the working command looks like:I think we should copy all the required
.afiles into the publish directory and create a helper script (.sh) for the user.