Skip to content

Commit 62501de

Browse files
committed
try to display meaningful error messages when native library load fails
1 parent 5fe0ab9 commit 62501de

File tree

1 file changed

+39
-10
lines changed

1 file changed

+39
-10
lines changed

RocksDbSharp/AutoNativeImport.cs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public static class Importers
5555

5656
private class WindowsImporter : INativeLibImporter
5757
{
58-
[DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
58+
[DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]
5959
public static extern IntPtr WinLoadLibrary(string dllToLoad);
6060

6161
[DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
@@ -66,7 +66,10 @@ private class WindowsImporter : INativeLibImporter
6666

6767
public IntPtr LoadLibrary(string path)
6868
{
69-
return WinLoadLibrary(path);
69+
var result = WinLoadLibrary(path);
70+
if (result == IntPtr.Zero)
71+
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
72+
return result;
7073
}
7174

7275
public IntPtr GetProcAddress(IntPtr lib, string entryPoint)
@@ -134,25 +137,27 @@ static string GetPlatform()
134137
Marshal.FreeHGlobal(buf);
135138
}
136139
}
140+
137141
public IntPtr LoadLibrary(string path)
138142
{
139143
dlerror();
140144
var lib = dlopen(path, 2);
141-
/*
142145
var errPtr = dlerror();
143146
if (errPtr != IntPtr.Zero)
144147
throw new NativeLoadException("dlopen: " + Marshal.PtrToStringAnsi(errPtr), null);
145-
*/
146148
return lib;
147149
}
148150

149151
public IntPtr GetProcAddress(IntPtr lib, string entryPoint)
150152
{
151153
dlerror();
152154
IntPtr address = dlsym(lib, entryPoint);
153-
var errPtr = dlerror();
154-
if (errPtr != IntPtr.Zero)
155-
throw new NativeLoadException("dlsym: " + Marshal.PtrToStringAnsi(errPtr), null);
155+
if (address == IntPtr.Zero)
156+
{
157+
var errPtr = dlerror();
158+
if (errPtr != IntPtr.Zero)
159+
throw new NativeLoadException("dlsym: " + Marshal.PtrToStringAnsi(errPtr), null);
160+
}
156161
return address;
157162
}
158163

@@ -174,6 +179,8 @@ public static T LoadFunc<T>(INativeLibImporter importer, IntPtr libraryHandle, s
174179
IntPtr procAddress = importer.GetProcAddress(libraryHandle, entryPoint);
175180
if (procAddress == IntPtr.Zero)
176181
{
182+
throw new Exception($"Cannot get proc address of {entryPoint}");
183+
/*
177184
var invokeMethod = typeof(T).GetTypeInfo().GetMethod("Invoke");
178185
var parameters = invokeMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType)).ToArray();
179186
var returnType = invokeMethod.ReturnType;
@@ -184,6 +191,7 @@ public static T LoadFunc<T>(INativeLibImporter importer, IntPtr libraryHandle, s
184191
var block = Expression.Block(returnType, Expression.Invoke(callThrowExpr), defaultExpr);
185192
var lambda = Expression.Lambda<T>(block, parameters);
186193
return lambda.Compile();
194+
*/
187195
}
188196
return CurrentFramework.GetDelegateForFunctionPointer<T>(procAddress);
189197
}
@@ -359,20 +367,41 @@ public static T Import<T>(INativeLibImporter importer, string libName, string ve
359367
paths.SelectMany(path => names.Select(n => Path.Combine(basePath, path, importer.Translate(n))))
360368
.Concat(names.Select(n => importer.Translate(n)))
361369
)
370+
.Select(path => new SearchPath { Path = path })
362371
.ToArray();
363372

364373
foreach (var spec in search)
365374
{
366375
var construct = type.GetConstructor(new Type[] { typeof(INativeLibImporter), typeof(IntPtr) });
367-
var lib = importer.LoadLibrary(spec);
368-
if (lib == IntPtr.Zero)
376+
IntPtr lib = IntPtr.Zero;
377+
try
378+
{
379+
lib = importer.LoadLibrary(spec.Path);
380+
if (lib == IntPtr.Zero)
381+
throw new NativeLoadException("LoadLibrary returned 0", null);
382+
}
383+
catch (TargetInvocationException tie)
384+
{
385+
spec.Error = tie.InnerException;
386+
continue;
387+
}
388+
catch (Exception e)
389+
{
390+
spec.Error = e;
369391
continue;
392+
}
370393
var obj = construct.Invoke(new object[] { importer, lib });
371394
var t = obj as T;
372395
return t;
373396
}
374397

375-
throw new NativeLoadException("Unable to locate rocksdb native library, either install it, or use RocksDbNative nuget package\nSearched:" + string.Join("\n", search), null);
398+
throw new NativeLoadException("Unable to locate rocksdb native library, either install it, or use RocksDbNative nuget package\nSearched:" + string.Join("\n", search.Select(s => $"{s.Path}: ({s.Error.GetType().Name}) {s.Error.Message}")), null);
399+
}
400+
401+
private class SearchPath
402+
{
403+
public string Path { get; set; }
404+
public Exception Error { get; set; }
376405
}
377406

378407
private static string GetMethodSig(MethodInfo m)

0 commit comments

Comments
 (0)