@@ -46,13 +46,34 @@ public interface INativeLibImporter
46
46
IntPtr GetProcAddress ( IntPtr lib , string entryPoint ) ;
47
47
void FreeLibrary ( IntPtr lib ) ;
48
48
string Translate ( string name ) ;
49
+ object GetDelegate ( IntPtr lib , string entryPoint , Type delegateType ) ;
49
50
}
50
51
51
52
public static class Importers
52
53
{
53
54
public static INativeLibImporter Windows = new WindowsImporter ( ) ;
54
55
public static INativeLibImporter Posix = new PosixImporter ( ) ;
55
56
57
+ static object GetDelegate ( INativeLibImporter importer , IntPtr lib , string entryPoint , Type delegateType )
58
+ {
59
+ IntPtr procAddress = importer . GetProcAddress ( lib , entryPoint ) ;
60
+ if ( procAddress == IntPtr . Zero )
61
+ {
62
+ var invokeMethod = delegateType . GetTypeInfo ( ) . GetMethod ( "Invoke" ) ;
63
+ var parameters = invokeMethod . GetParameters ( ) . Select ( p => Expression . Parameter ( p . ParameterType ) ) . ToArray ( ) ;
64
+ var returnType = invokeMethod . ReturnType ;
65
+ var errorMessage = string . Format ( "Unable to get address of {0} ({1})" , entryPoint , delegateType ) ;
66
+ Action throwAction = ( ) => throw new NativeLoadException ( errorMessage , null ) ;
67
+ var callThrowExpr = Expression . Constant ( throwAction , typeof ( Action ) ) ;
68
+ var defaultExpr = Expression . Default ( returnType ) ;
69
+ var block = Expression . Block ( returnType , Expression . Invoke ( callThrowExpr ) , defaultExpr ) ;
70
+ var lambda = Expression . Lambda ( delegateType , block , parameters ) ;
71
+ return lambda . Compile ( ) ;
72
+ }
73
+ var method = typeof ( CurrentFramework ) . GetTypeInfo ( ) . GetMethod ( nameof ( CurrentFramework . GetDelegateForFunctionPointer ) ) . MakeGenericMethod ( delegateType ) ;
74
+ return method . Invoke ( null , new object [ ] { procAddress } ) ;
75
+ }
76
+
56
77
private class WindowsImporter : INativeLibImporter
57
78
{
58
79
[ DllImport ( "kernel32.dll" , EntryPoint = "LoadLibrary" , SetLastError = true ) ]
@@ -78,6 +99,9 @@ public IntPtr GetProcAddress(IntPtr lib, string entryPoint)
78
99
return address ;
79
100
}
80
101
102
+ public object GetDelegate ( IntPtr lib , string entryPoint , Type delegateType )
103
+ => Importers . GetDelegate ( this , lib , entryPoint , delegateType ) ;
104
+
81
105
public void FreeLibrary ( IntPtr lib )
82
106
{
83
107
WinFreeLibrary ( lib ) ;
@@ -161,6 +185,9 @@ public IntPtr GetProcAddress(IntPtr lib, string entryPoint)
161
185
return address ;
162
186
}
163
187
188
+ public object GetDelegate ( IntPtr lib , string entryPoint , Type delegateType )
189
+ => Importers . GetDelegate ( this , lib , entryPoint , delegateType ) ;
190
+
164
191
public void FreeLibrary ( IntPtr lib )
165
192
{
166
193
dlclose ( lib ) ;
@@ -172,31 +199,6 @@ public string Translate(string name)
172
199
}
173
200
}
174
201
175
- public static class U
176
- {
177
- public static T LoadFunc < T > ( INativeLibImporter importer , IntPtr libraryHandle , string entryPoint )
178
- {
179
- IntPtr procAddress = importer . GetProcAddress ( libraryHandle , entryPoint ) ;
180
- if ( procAddress == IntPtr . Zero )
181
- {
182
- throw new Exception ( $ "Cannot get proc address of { entryPoint } ") ;
183
- /*
184
- var invokeMethod = typeof(T).GetTypeInfo().GetMethod("Invoke");
185
- var parameters = invokeMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType)).ToArray();
186
- var returnType = invokeMethod.ReturnType;
187
- var errorMessage = string.Format("Unable to get address of {0} ({1})", entryPoint, typeof(T));
188
- Action throwAction = () => throw new NativeLoadException(errorMessage, null);
189
- var callThrowExpr = Expression.Constant(throwAction, typeof(Action));
190
- var defaultExpr = Expression.Default(returnType);
191
- var block = Expression.Block(returnType, Expression.Invoke(callThrowExpr), defaultExpr);
192
- var lambda = Expression.Lambda<T>(block, parameters);
193
- return lambda.Compile();
194
- */
195
- }
196
- return CurrentFramework . GetDelegateForFunctionPointer < T > ( procAddress ) ;
197
- }
198
- }
199
-
200
202
public static string GetArchName ( Architecture arch )
201
203
{
202
204
switch ( arch )
@@ -241,8 +243,7 @@ public static T Import<T>(INativeLibImporter importer, string libName, string ve
241
243
MethodInfo = m ,
242
244
DelegateType = delegateMap [ GetMethodSig ( m ) ] ,
243
245
} ) . ToArray ( ) ;
244
- var fields = delegates . Select ( d => typeBuilder . DefineField ( d . MethodInfo . Name + "_func" , d . DelegateType , FieldAttributes . Private ) ) . ToArray ( ) ;
245
-
246
+ var fields = delegates . Select ( ( d , i ) => typeBuilder . DefineField ( $ "{ d . MethodInfo . Name } _func_{ i } ", d . DelegateType , FieldAttributes . Private ) ) . ToArray ( ) ;
246
247
247
248
// Create the constructor which will initialize the importer and library handle
248
249
// and also use the importer to populate each of the delegate fields
@@ -266,19 +267,22 @@ public static T Import<T>(INativeLibImporter importer, string libName, string ve
266
267
il . Emit ( OpCodes . Ldarg_2 ) ; // library handle
267
268
il . Emit ( OpCodes . Stfld , field_libraryHandle ) ;
268
269
270
+ var getDelegateMethod = typeof ( INativeLibImporter ) . GetTypeInfo ( ) . GetMethod ( "GetDelegate" ) ;
269
271
// Initialize each delegate field
270
272
for ( int i = 0 ; i < fields . Length ; i ++ )
271
273
{
274
+ var delegateType = delegates [ i ] . DelegateType ;
275
+
272
276
il . Emit ( OpCodes . Ldarg_0 ) ; // this
277
+
273
278
il . Emit ( OpCodes . Ldarg_1 ) ; // importer
274
279
il . Emit ( OpCodes . Ldarg_0 ) ; // this
275
280
il . Emit ( OpCodes . Ldfld , field_libraryHandle ) ;
276
281
il . Emit ( OpCodes . Ldstr , delegates [ i ] . MethodInfo . Name ) ; // use method name from original class as entry point
277
- var delegateType = delegates [ i ] . DelegateType ;
278
- //il.Emit(OpCodes.Ldtoken, delegateType); // the delegate type
279
- //il.Emit(OpCodes.Call, typeof(System.Type).GetTypeInfo().GetMethod("GetTypeFromHandle")); // typeof()
280
- il . Emit ( OpCodes . Call , typeof ( U ) . GetTypeInfo ( ) . GetMethod ( "LoadFunc" ) . MakeGenericMethod ( delegateType ) ) ; // U.LoadFunc<delegate type>()
281
- //il.Emit(OpCodes.Isinst, delegates[i].DelegateType); // as <delegate type>
282
+ il . Emit ( OpCodes . Ldtoken , delegateType ) ; // the delegate type
283
+ il . Emit ( OpCodes . Call , typeof ( System . Type ) . GetTypeInfo ( ) . GetMethod ( "GetTypeFromHandle" ) ) ; // typeof()
284
+ il . Emit ( OpCodes . Callvirt , getDelegateMethod ) ; // importer.GetDelegate()
285
+ il . Emit ( OpCodes . Isinst , delegateType ) ; // as <delegate type>
282
286
il . Emit ( OpCodes . Stfld , fields [ i ] ) ;
283
287
}
284
288
0 commit comments