Skip to content

Commit 7b239f1

Browse files
committed
fix handling of missing entry points for entry points that contain pointers
1 parent 3267af9 commit 7b239f1

File tree

1 file changed

+31
-21
lines changed

1 file changed

+31
-21
lines changed

RocksDbSharp/AutoNativeImport.cs

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,7 @@ static object GetDelegate(INativeLibImporter importer, IntPtr lib, string entryP
6161
{
6262
IntPtr procAddress = importer.GetProcAddress(lib, entryPoint);
6363
if (procAddress == IntPtr.Zero)
64-
{
65-
var invokeMethod = delegateType.GetTypeInfo().GetMethod("Invoke");
66-
var parameters = invokeMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType)).ToArray();
67-
var returnType = invokeMethod.ReturnType;
68-
var errorMessage = string.Format("Unable to get address of {0} ({1})", entryPoint, delegateType);
69-
Action throwAction = () => throw new NativeLoadException(errorMessage, null);
70-
var callThrowExpr = Expression.Constant(throwAction, typeof(Action));
71-
var defaultExpr = Expression.Default(returnType);
72-
var block = Expression.Block(returnType, Expression.Invoke(callThrowExpr), defaultExpr);
73-
var lambda = Expression.Lambda(delegateType, block, parameters);
74-
return lambda.Compile();
75-
}
64+
return null;
7665
var method = typeof(CurrentFramework).GetTypeInfo().GetMethod(nameof(CurrentFramework.GetDelegateForFunctionPointer)).MakeGenericMethod(delegateType);
7766
return method.Invoke(null, new object[] { procAddress });
7867
}
@@ -240,7 +229,7 @@ public static T Import<T>(INativeLibImporter importer, string libName, string ve
240229
MethodInfo = m,
241230
DelegateType = delegateMap[GetMethodSig(m)],
242231
}).ToArray();
243-
var fields = delegates.Select((d, i) => typeBuilder.DefineField($"{d.MethodInfo.Name}_func_{i}", d.DelegateType, FieldAttributes.Private)).ToArray();
232+
var delegateFields = delegates.Select((d, i) => typeBuilder.DefineField($"{d.MethodInfo.Name}_func_{i}", d.DelegateType, FieldAttributes.Private)).ToArray();
244233

245234
// Create the constructor which will initialize the importer and library handle
246235
// and also use the importer to populate each of the delegate fields
@@ -266,7 +255,7 @@ public static T Import<T>(INativeLibImporter importer, string libName, string ve
266255

267256
var getDelegateMethod = typeof(INativeLibImporter).GetTypeInfo().GetMethod("GetDelegate");
268257
// Initialize each delegate field
269-
for (int i = 0; i < fields.Length; i++)
258+
for (int i = 0; i < delegateFields.Length; i++)
270259
{
271260
var delegateType = delegates[i].DelegateType;
272261

@@ -280,7 +269,7 @@ public static T Import<T>(INativeLibImporter importer, string libName, string ve
280269
il.Emit(OpCodes.Call, typeof(System.Type).GetTypeInfo().GetMethod("GetTypeFromHandle")); // typeof()
281270
il.Emit(OpCodes.Callvirt, getDelegateMethod); // importer.GetDelegate()
282271
il.Emit(OpCodes.Isinst, delegateType); // as <delegate type>
283-
il.Emit(OpCodes.Stfld, fields[i]);
272+
il.Emit(OpCodes.Stfld, delegateFields[i]);
284273
}
285274

286275
// End of constructor
@@ -313,21 +302,25 @@ public static T Import<T>(INativeLibImporter importer, string libName, string ve
313302
il.Emit(OpCodes.Ret);
314303
}
315304

305+
var nativeFunctionMissingExceptionConstructor = typeof(NativeFunctionMissingException).GetTypeInfo().GetConstructor(new[] { typeof(string) });
316306
// Now override each method from the base class
317-
for (int i = 0; i < fields.Length; i++)
307+
for (int i = 0; i < delegateFields.Length; i++)
318308
{
319309
var baseMethod = delegates[i].MethodInfo;
320310
var args = baseMethod.GetParameters();
321311
var omethod = typeBuilder.DefineMethod(
322-
baseMethod.Name,
323-
(baseMethod.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot)) | MethodAttributes.Virtual,
324-
baseMethod.CallingConvention,
325-
baseMethod.ReturnType,
312+
baseMethod.Name,
313+
(baseMethod.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot)) | MethodAttributes.Virtual,
314+
baseMethod.CallingConvention,
315+
baseMethod.ReturnType,
326316
args.Select(arg => arg.ParameterType).ToArray()
327317
);
328318
var il = omethod.GetILGenerator();
329319
il.Emit(OpCodes.Ldarg_0); // this
330-
il.Emit(OpCodes.Ldfld, fields[i]); // {field}
320+
il.Emit(OpCodes.Ldfld, delegateFields[i]); // {field}
321+
il.Emit(OpCodes.Dup);
322+
var error = il.DefineLabel();
323+
il.Emit(OpCodes.Brfalse_S, error);
331324
if (args.Length >= 1)
332325
il.Emit(OpCodes.Ldarg_1);
333326
if (args.Length >= 2)
@@ -339,6 +332,10 @@ public static T Import<T>(INativeLibImporter importer, string libName, string ve
339332
il.Emit(OpCodes.Tailcall);
340333
il.Emit(OpCodes.Callvirt, delegates[i].DelegateType.GetTypeInfo().GetMethod("Invoke"));
341334
il.Emit(OpCodes.Ret);
335+
il.MarkLabel(error);
336+
il.Emit(OpCodes.Ldstr, baseMethod.ToString());
337+
il.Emit(OpCodes.Newobj, nativeFunctionMissingExceptionConstructor);
338+
il.Emit(OpCodes.Throw);
342339
}
343340

344341
var type = typeBuilder.CreateTypeInfo();
@@ -453,6 +450,19 @@ private static TypeInfo CreateDelegateType(ModuleBuilder moduleBuilder, MethodIn
453450

454451
}
455452

453+
public class NativeFunctionMissingException : Exception
454+
{
455+
public NativeFunctionMissingException()
456+
: base("Failed to find entry point")
457+
{
458+
}
459+
460+
public NativeFunctionMissingException(string entryPoint)
461+
: base($"Failed to find entry point for {entryPoint}", null)
462+
{
463+
}
464+
}
465+
456466
public class NativeLoadException : Exception
457467
{
458468
public NativeLoadException(string message, Exception inner)

0 commit comments

Comments
 (0)