From 22a2d72cfbfe8888a7d4f96d520a88c3123a6990 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Sat, 7 Jan 2023 18:55:31 +0600 Subject: [PATCH 1/4] Update to .NET 7 paths and add error reporting I by mistake compile from x86 dev tools on Windows and that cause silent error failure. Hopefully my error reporting does not clutter code too much. /cc @MichalStrehovsky --- core/nativeaot/NativeLibrary/LoadLibrary.c | 29 +++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/core/nativeaot/NativeLibrary/LoadLibrary.c b/core/nativeaot/NativeLibrary/LoadLibrary.c index 4d82fae7dcb..179920dda72 100644 --- a/core/nativeaot/NativeLibrary/LoadLibrary.c +++ b/core/nativeaot/NativeLibrary/LoadLibrary.c @@ -1,15 +1,12 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - //On unix make sure to compile using -ldl and -pthread flags. //Set this value accordingly to your workspace settings #if defined(_WIN32) -#define PathToLibrary "bin\\Debug\\net6.0\\win-x64\\native\\NativeLibrary.dll" +#define PathToLibrary "bin\\Debug\\net7.0\\win-x64\\native\\NativeLibrary.dll" #elif defined(__APPLE__) -#define PathToLibrary "./bin/Debug/net6.0/osx-x64/native/NativeLibrary.dylib" +#define PathToLibrary "./bin/Debug/net7.0/osx-x64/native/NativeLibrary.dylib" #else -#define PathToLibrary "./bin/Debug/net6.0/linux-x64/native/NativeLibrary.so" +#define PathToLibrary "./bin/Debug/net7.0/linux-x64/native/NativeLibrary.so" #endif #ifdef _WIN32 @@ -60,6 +57,16 @@ int callSumFunc(char *path, char *funcName, int firstInt, int secondInt) #else void *handle = dlopen(path, RTLD_LAZY); #endif + if (!handle) + { +#ifdef _WIN32 + int errorCode = GetLastError(); + printf("Failed to load library at specified path. Error code: %d\n", errorCode); +#else + puts("Failed to load library at specified path"); +#endif + return -1; + } typedef int(*myFunc)(int,int); myFunc MyImport = (myFunc)symLoad(handle, funcName); @@ -79,6 +86,16 @@ char *callSumStringFunc(char *path, char *funcName, char *firstString, char *sec #else void *handle = dlopen(path, RTLD_LAZY); #endif + if (!handle) + { +#ifdef _WIN32 + int errorCode = GetLastError(); + printf("Failed to load library at specified path. Error code: %d\n", errorCode); +#else + puts("Failed to load library at specified path"); +#endif + return nullptr; + } // Declare a typedef typedef char *(*myFunc)(char*,char*); From 753ea0a803b64e287e1614ed716fce2719cd3c60 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Sat, 7 Jan 2023 18:57:03 +0600 Subject: [PATCH 2/4] Restore back license header --- core/nativeaot/NativeLibrary/LoadLibrary.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/nativeaot/NativeLibrary/LoadLibrary.c b/core/nativeaot/NativeLibrary/LoadLibrary.c index 179920dda72..98aa61ccc86 100644 --- a/core/nativeaot/NativeLibrary/LoadLibrary.c +++ b/core/nativeaot/NativeLibrary/LoadLibrary.c @@ -1,3 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + //On unix make sure to compile using -ldl and -pthread flags. //Set this value accordingly to your workspace settings From 10ef32ac38cd3e7f8b9d69479362628a3cc6017e Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Mon, 9 Jan 2023 10:25:29 +0600 Subject: [PATCH 3/4] Rename file and class name to have nice names --- core/nativeaot/NativeLibrary/Class1.cs | 55 ------------------- .../NativeLibrary/LibraryFunctions.cs | 54 ++++++++++++++++++ 2 files changed, 54 insertions(+), 55 deletions(-) delete mode 100644 core/nativeaot/NativeLibrary/Class1.cs create mode 100644 core/nativeaot/NativeLibrary/LibraryFunctions.cs diff --git a/core/nativeaot/NativeLibrary/Class1.cs b/core/nativeaot/NativeLibrary/Class1.cs deleted file mode 100644 index cef6ce17c4a..00000000000 --- a/core/nativeaot/NativeLibrary/Class1.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Runtime.InteropServices; - -namespace NativeLibrary -{ - public class Class1 - { - [UnmanagedCallersOnly(EntryPoint = "add")] - public static int Add(int a, int b) - { - return a + b; - } - - [UnmanagedCallersOnly(EntryPoint = "write_line")] - public static int WriteLine(IntPtr pString) - { - // The marshalling code is typically auto-generated by a custom tool in larger projects. - try - { - // UnmanagedCallersOnly methods only accept primitive arguments. The primitive arguments - // have to be marshalled manually if necessary. - string str = Marshal.PtrToStringAnsi(pString); - - Console.WriteLine(str); - } - catch - { - // Exceptions escaping out of UnmanagedCallersOnly methods are treated as unhandled exceptions. - // The errors have to be marshalled manually if necessary. - return -1; - } - return 0; - } - - [UnmanagedCallersOnly(EntryPoint = "sumstring")] - public static IntPtr sumstring(IntPtr first, IntPtr second) - { - // Parse strings from the passed pointers - string my1String = Marshal.PtrToStringAnsi(first); - string my2String = Marshal.PtrToStringAnsi(second); - - // Concatenate strings - string sum = my1String + my2String; - - // Assign pointer of the concatenated string to sumPointer - IntPtr sumPointer = Marshal.StringToHGlobalAnsi(sum); - - // Return pointer - return sumPointer; - } - } -} diff --git a/core/nativeaot/NativeLibrary/LibraryFunctions.cs b/core/nativeaot/NativeLibrary/LibraryFunctions.cs new file mode 100644 index 00000000000..b247e9c2869 --- /dev/null +++ b/core/nativeaot/NativeLibrary/LibraryFunctions.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace NativeLibrary; + +public class LibraryFunctions +{ + [UnmanagedCallersOnly(EntryPoint = "add")] + public static int Add(int a, int b) + { + return a + b; + } + + [UnmanagedCallersOnly(EntryPoint = "write_line")] + public static int WriteLine(IntPtr pString) + { + // The marshalling code is typically auto-generated by a custom tool in larger projects. + try + { + // UnmanagedCallersOnly methods only accept primitive arguments. The primitive arguments + // have to be marshalled manually if necessary. + string str = Marshal.PtrToStringAnsi(pString); + + Console.WriteLine(str); + } + catch + { + // Exceptions escaping out of UnmanagedCallersOnly methods are treated as unhandled exceptions. + // The errors have to be marshalled manually if necessary. + return -1; + } + return 0; + } + + [UnmanagedCallersOnly(EntryPoint = "sumstring")] + public static IntPtr sumstring(IntPtr first, IntPtr second) + { + // Parse strings from the passed pointers + string my1String = Marshal.PtrToStringAnsi(first); + string my2String = Marshal.PtrToStringAnsi(second); + + // Concatenate strings + string sum = my1String + my2String; + + // Assign pointer of the concatenated string to sumPointer + IntPtr sumPointer = Marshal.StringToHGlobalAnsi(sum); + + // Return pointer + return sumPointer; + } +} From f2f2a90bd2dcf7f5982bc504defeef1a6bd18efb Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Mon, 9 Jan 2023 10:27:29 +0600 Subject: [PATCH 4/4] Fix PR feedback --- core/nativeaot/NativeLibrary/LoadLibrary.c | 47 +++++++++------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/core/nativeaot/NativeLibrary/LoadLibrary.c b/core/nativeaot/NativeLibrary/LoadLibrary.c index 98aa61ccc86..b192bc15779 100644 --- a/core/nativeaot/NativeLibrary/LoadLibrary.c +++ b/core/nativeaot/NativeLibrary/LoadLibrary.c @@ -31,6 +31,8 @@ int callSumFunc(char *path, char *funcName, int a, int b); char *callSumStringFunc(char *path, char *funcName, char *a, char *b); +void* loadSymbol(char *path, char *funcName); + int main() { // Check if the library file exists @@ -52,9 +54,9 @@ int main() free(sumstring); } -int callSumFunc(char *path, char *funcName, int firstInt, int secondInt) +void *loadSymbol(char *path, char *funcName) { - // Call sum function defined in C# shared library + // Library loading #ifdef _WIN32 HINSTANCE handle = LoadLibraryA(path); #else @@ -68,48 +70,37 @@ int callSumFunc(char *path, char *funcName, int firstInt, int secondInt) #else puts("Failed to load library at specified path"); #endif - return -1; + return NULL; } - typedef int(*myFunc)(int,int); - myFunc MyImport = (myFunc)symLoad(handle, funcName); + // Declare a typedef + typedef char *(*myFunc)(char*,char*); - int result = MyImport(firstInt, secondInt); + // Import Symbol named funcName - // CoreRT libraries do not support unloading + // NativeAOT libraries do not support unloading // See https://github.com/dotnet/corert/issues/7887 + return symLoad(handle, funcName); +} + +int callSumFunc(char *path, char *funcName, int firstInt, int secondInt) +{ + typedef int(*myFunc)(int,int); + myFunc MyImport = (myFunc)loadSymbol(path, funcName); + + int result = MyImport(firstInt, secondInt); return result; } char *callSumStringFunc(char *path, char *funcName, char *firstString, char *secondString) { - // Library loading - #ifdef _WIN32 - HINSTANCE handle = LoadLibraryA(path); - #else - void *handle = dlopen(path, RTLD_LAZY); - #endif - if (!handle) - { -#ifdef _WIN32 - int errorCode = GetLastError(); - printf("Failed to load library at specified path. Error code: %d\n", errorCode); -#else - puts("Failed to load library at specified path"); -#endif - return nullptr; - } - // Declare a typedef typedef char *(*myFunc)(char*,char*); // Import Symbol named funcName - myFunc MyImport = (myFunc)symLoad(handle, funcName); + myFunc MyImport = (myFunc)loadSymbol(path, funcName); // The C# function will return a pointer char *result = MyImport(firstString, secondString); - - // CoreRT libraries do not support unloading - // See https://github.com/dotnet/corert/issues/7887 return result; }