public static void LinuxX64Callback(string format, IntPtr args) { // The args pointer cannot be reused between two calls. We need to make a copy of the underlying structure. var listStructure = Marshal.PtrToStructure <VaListLinuxX64>(args); int byteLength = 0; UseStructurePointer(listStructure, listPointer => { byteLength = LinuxInterop.vsnprintf(IntPtr.Zero, UIntPtr.Zero, format, listPointer) + 1; }); var utf8Buffer = Marshal.AllocHGlobal(byteLength); try { UseStructurePointer(listStructure, listPointer => { LinuxInterop.vsprintf(utf8Buffer, format, listPointer); Console.WriteLine(Utf8ToString(utf8Buffer)); }); } finally { Marshal.FreeHGlobal(utf8Buffer); } }
public static void RunUnix() { string arch; NativeLibrary.Callback callback; // Detect the process architecture switch (RuntimeInformation.ProcessArchitecture) { case Architecture.X86: arch = "x86"; callback = LinuxX86Callback; break; case Architecture.X64: arch = "x64"; callback = LinuxX64Callback; break; default: throw new PlatformNotSupportedException("Only x86 and x64 are supported at the moment"); } Console.WriteLine(arch); // Load the correct library var nativeExtension = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "so " : "dylib"; var handle = LinuxInterop.dlopen(Path.Combine(Environment.CurrentDirectory, "nativeLibrary", "build", $"libnativeLibrary.{arch}.{nativeExtension}"), LinuxInterop.RTLD_LAZY); if (handle == IntPtr.Zero) { Console.Error.WriteLine("Failed to load native library"); throw new Exception(LinuxInterop.dlerror()); } try { // Locate the "triggerCallback" function. This function just calls the callback with some parameters. var procAddress = LinuxInterop.dlsym(handle, "triggerCallback"); if (procAddress == IntPtr.Zero) { Console.Error.WriteLine("Failed to locate the triggerCallback function."); throw new Exception(LinuxInterop.dlerror()); } var triggerCallback = Marshal.GetDelegateForFunctionPointer <NativeLibrary.TriggerCallback>(procAddress); triggerCallback(callback); } finally { LinuxInterop.dlclose(handle); } }
public static void LinuxX86Callback(string format, IntPtr args) { // This implementation is pretty straightforward. The IntPtr can be passed to the functions and can be reused. int byteLength = LinuxInterop.vsnprintf(IntPtr.Zero, UIntPtr.Zero, format, args) + 1; var utf8Buffer = Marshal.AllocHGlobal(byteLength); try { LinuxInterop.vsprintf(utf8Buffer, format, args); Console.WriteLine(Utf8ToString(utf8Buffer)); } finally { Marshal.FreeHGlobal(utf8Buffer); } }