public static bool Initialize(string userSpecifiedPath) { lock (loadLockObj) { if (isInitialized) { return(false); } isInitialized = false; #if NET45 || NET46 || NET47 string path = userSpecifiedPath; if (path == null) { // in net45, librdkafka.dll is not in the process directory, we have to load it manually // and also search in the same folder for its dependencies (LOAD_WITH_ALTERED_SEARCH_PATH) var is64 = IntPtr.Size == 8; var baseUri = new Uri(Assembly.GetExecutingAssembly().GetName().EscapedCodeBase); var baseDirectory = Path.GetDirectoryName(baseUri.LocalPath); var dllDirectory = Path.Combine( baseDirectory, is64 ? Path.Combine("librdkafka", "x64") : Path.Combine("librdkafka", "x86")); path = Path.Combine(dllDirectory, "librdkafka.dll"); if (!File.Exists(path)) { dllDirectory = Path.Combine( baseDirectory, is64 ? @"runtimes\win7-x64\native" : @"runtimes\win7-x86\native"); path = Path.Combine(dllDirectory, "librdkafka.dll"); } } if (WindowsNative.LoadLibraryEx(path, IntPtr.Zero, WindowsNative.LoadLibraryFlags.LOAD_WITH_ALTERED_SEARCH_PATH) == IntPtr.Zero) { // catch the last win32 error by default and keep the associated default message var win32Exception = new Win32Exception(); var additionalMessage = $"Error while loading librdkafka.dll or its dependencies from {path}. " + $"Check the directory exists, if not check your deployment process. " + $"You can also load the library and its dependencies by yourself " + $"before any call to Confluent.Kafka"; throw new InvalidOperationException(additionalMessage, win32Exception); } isInitialized = SetDelegates(typeof(NativeMethods.NativeMethods)); #else const int RTLD_NOW = 2; var nativeMethodTypes = new List <Type>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (userSpecifiedPath != null) { if (WindowsNative.LoadLibraryEx(userSpecifiedPath, IntPtr.Zero, WindowsNative.LoadLibraryFlags.LOAD_WITH_ALTERED_SEARCH_PATH) == IntPtr.Zero) { // TODO: The Win32Exception class is not available in .NET Standard, which is the easy way to get the message string corresponding to // a win32 error. FormatMessage is not straightforward to p/invoke, so leaving this as a job for another day. throw new InvalidOperationException($"Failed to load librdkafka at location '{userSpecifiedPath}'. Win32 error: {Marshal.GetLastWin32Error()}"); } } nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods)); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (userSpecifiedPath != null) { if (PosixNative.dlopen(userSpecifiedPath, RTLD_NOW) == IntPtr.Zero) { throw new InvalidOperationException($"Failed to load librdkafka at location '{userSpecifiedPath}'. dlerror: '{PosixNative.LastError}'."); } } nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods)); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { if (userSpecifiedPath != null) { if (PosixNative.dlopen(userSpecifiedPath, RTLD_NOW) == IntPtr.Zero) { throw new InvalidOperationException($"Failed to load librdkafka at location '{userSpecifiedPath}'. dlerror: '{PosixNative.LastError}'."); } nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods)); } else { nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods)); nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods_Debian9)); } } else { throw new InvalidOperationException($"Unsupported platform: {RuntimeInformation.OSDescription}"); } foreach (var t in nativeMethodTypes) { isInitialized = SetDelegates(t); if (isInitialized) { break; } } #endif if (!isInitialized) { throw new DllNotFoundException("Failed to load the librdkafka native library."); } if ((long)version() < minVersion) { throw new FileLoadException($"Invalid librdkafka version {(long)version():x}, expected at least {minVersion:x}"); } isInitialized = true; // Protect the _destroy and _destroyMethodInfo objects from garbage collection. This is // required since the Producer/Consumer finalizers may reference them, and they might // have otherwise been cleaned up at that point. To keep things simple, there is no reference // counting / corresponding Free() call - there is negligible overhead in keeping these // references around for the lifetime of the process. GCHandle.Alloc(_destroy, GCHandleType.Normal); GCHandle.Alloc(_destroyMethodInfo, GCHandleType.Normal); return(isInitialized); } }
private static bool InitializeDotNetCore(string userSpecifiedPath) { const int RTLD_NOW = 2; var nativeMethodTypes = new List <Type>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (userSpecifiedPath != null) { if (WindowsNative.LoadLibraryEx(userSpecifiedPath, IntPtr.Zero, WindowsNative.LoadLibraryFlags.LOAD_WITH_ALTERED_SEARCH_PATH) == IntPtr.Zero) { // TODO: The Win32Exception class is not available in .NET Standard, which is the easy way to get the message string corresponding to // a win32 error. FormatMessage is not straightforward to p/invoke, so leaving this as a job for another day. throw new InvalidOperationException($"Failed to load librdkafka at location '{userSpecifiedPath}'. Win32 error: {Marshal.GetLastWin32Error()}"); } } nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods)); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (userSpecifiedPath != null) { if (PosixNative.dlopen(userSpecifiedPath, RTLD_NOW) == IntPtr.Zero) { throw new InvalidOperationException($"Failed to load librdkafka at location '{userSpecifiedPath}'. dlerror: '{PosixNative.LastError}'."); } } nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods)); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { if (userSpecifiedPath != null) { if (PosixNative.dlopen(userSpecifiedPath, RTLD_NOW) == IntPtr.Zero) { throw new InvalidOperationException($"Failed to load librdkafka at location '{userSpecifiedPath}'. dlerror: '{PosixNative.LastError}'."); } nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods)); } else { nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods)); nativeMethodTypes.Add(typeof(NativeMethods.NativeMethods_Debian9)); } } else { throw new InvalidOperationException($"Unsupported platform: {RuntimeInformation.OSDescription}"); } foreach (var t in nativeMethodTypes) { if (SetDelegates(t)) { return(true); } } return(false); }