@@ -16,8 +16,10 @@ public class DllManipulator : MonoBehaviour
1616 public const string DLL_PATH_PATTERN_NAME_MACRO = "{name}" ;
1717 public const string DLL_PATH_PATTERN_ASSETS_MACRO = "{assets}" ;
1818 public const string DLL_PATH_PATTERN_PROJECT_MACRO = "{proj}" ;
19- private static readonly Type [ ] DELEGATE_CTOR_PARAMETERS = new [ ] { typeof ( object ) , typeof ( IntPtr ) } ;
20- private static readonly Type [ ] UNMANAGED_FUNCTION_POINTER_ATTRIBUTE_CTOR_PARAMETERS = new [ ] { typeof ( CallingConvention ) } ;
19+ public static readonly Type [ ] SUPPORTED_PARAMATER_ATTRIBUTES = { typeof ( MarshalAsAttribute ) , typeof ( InAttribute ) , typeof ( OutAttribute ) } ;
20+ private static readonly Type [ ] DELEGATE_CTOR_PARAMETERS = { typeof ( object ) , typeof ( IntPtr ) } ;
21+ private static readonly Type [ ] UNMANAGED_FUNCTION_POINTER_ATTRIBUTE_CTOR_PARAMETERS = { typeof ( CallingConvention ) } ;
22+ private static readonly Type [ ] MARSHAL_AS_ATTRIBUTE_CTOR_PARAMETERS = { typeof ( UnmanagedType ) } ;
2123
2224 public DllManipulatorOptions Options = new DllManipulatorOptions ( )
2325 {
@@ -262,10 +264,10 @@ private static DynamicMethod CreateNewNativeFunctionMock(MethodInfo nativeMethod
262264 var targetDelegateInvokeMethod = nativeFunction . delegateType . GetMethod ( "Invoke" , BindingFlags . Instance | BindingFlags . Public ) ;
263265
264266 var mockedDynamicMethod = new DynamicMethod ( dllName + ":::" + nativeFunctionSymbol , nativeMethod . ReturnType , parametersTypes , typeof ( DllManipulator ) ) ;
265- mockedDynamicMethod . DefineParameter ( 0 , nativeMethod . ReturnParameter . Attributes , nativeMethod . ReturnParameter . Name ) ;
267+ mockedDynamicMethod . DefineParameter ( 0 , nativeMethod . ReturnParameter . Attributes , null ) ;
266268 for ( int i = 0 ; i < parameters . Length ; i ++ )
267269 {
268- mockedDynamicMethod . DefineParameter ( parameters [ i ] . Position , parameters [ i ] . Attributes , parameters [ i ] . Name ) ;
270+ mockedDynamicMethod . DefineParameter ( i + 1 , parameters [ i ] . Attributes , null ) ;
269271 }
270272
271273 if ( _nativeFunctionsField == null )
@@ -333,7 +335,7 @@ private static void AddNativeFunction(NativeFunction nativeFunction)
333335 _nativeFunctions [ _nativeFunctionsCount ++ ] = nativeFunction ;
334336 }
335337
336- private static Type CreateDelegateTypeForNativeFunctionSignature ( NativeFunctionSignature funcionSignature )
338+ private static Type CreateDelegateTypeForNativeFunctionSignature ( NativeFunctionSignature functionSignature )
337339 {
338340 if ( _customDelegateTypesModule == null )
339341 {
@@ -347,31 +349,81 @@ private static Type CreateDelegateTypeForNativeFunctionSignature(NativeFunctionS
347349
348350 //ufp = UnmanagedFunctionPointer
349351 var ufpAttrType = typeof ( UnmanagedFunctionPointerAttribute ) ;
350- var ufpAttrCtor = ufpAttrType . GetConstructor ( UNMANAGED_FUNCTION_POINTER_ATTRIBUTE_CTOR_PARAMETERS ) ;
351- var ufpAttrCtorArgValues = new object [ ] { funcionSignature . callingConvention } ;
352- var ufpAttrNamedFields = new [ ] {
352+ var ufpAttrCtor = ufpAttrType . GetConstructor ( UNMANAGED_FUNCTION_POINTER_ATTRIBUTE_CTOR_PARAMETERS ) ;
353+ object [ ] ufpAttrCtorArgValues = { functionSignature . callingConvention } ;
354+ FieldInfo [ ] ufpAttrNamedFields = {
353355 ufpAttrType . GetField ( nameof ( UnmanagedFunctionPointerAttribute . BestFitMapping ) , BindingFlags . Public | BindingFlags . Instance ) ,
354356 ufpAttrType . GetField ( nameof ( UnmanagedFunctionPointerAttribute . CharSet ) , BindingFlags . Public | BindingFlags . Instance ) ,
355357 ufpAttrType . GetField ( nameof ( UnmanagedFunctionPointerAttribute . SetLastError ) , BindingFlags . Public | BindingFlags . Instance ) ,
356358 ufpAttrType . GetField ( nameof ( UnmanagedFunctionPointerAttribute . ThrowOnUnmappableChar ) , BindingFlags . Public | BindingFlags . Instance ) ,
357359 } ;
358- var ufpAttrFieldValues = new object [ ] { funcionSignature . bestFitMapping , funcionSignature . charSet , funcionSignature . setLastError , funcionSignature . throwOnUnmappableChar } ;
360+ object [ ] ufpAttrFieldValues = { functionSignature . bestFitMapping , functionSignature . charSet , functionSignature . setLastError , functionSignature . throwOnUnmappableChar } ;
359361 var ufpAttrBuilder = new CustomAttributeBuilder ( ufpAttrCtor , ufpAttrCtorArgValues , ufpAttrNamedFields , ufpAttrFieldValues ) ;
360362 delBuilder . SetCustomAttribute ( ufpAttrBuilder ) ;
361363
362-
363364 var ctorBuilder = delBuilder . DefineConstructor ( MethodAttributes . RTSpecialName | MethodAttributes . HideBySig | MethodAttributes . Public ,
364365 CallingConventions . Standard , DELEGATE_CTOR_PARAMETERS ) ;
365366 ctorBuilder . SetImplementationFlags ( MethodImplAttributes . Runtime | MethodImplAttributes . Managed ) ;
366367
367368 var invokeBuilder = delBuilder . DefineMethod ( "Invoke" , MethodAttributes . Public | MethodAttributes . HideBySig | MethodAttributes . Virtual | MethodAttributes . NewSlot ,
368- CallingConventions . Standard | CallingConventions . HasThis , funcionSignature . returnParameterType , funcionSignature . parameterTypes ) ;
369+ CallingConventions . Standard | CallingConventions . HasThis , functionSignature . returnParameter . type , functionSignature . parameters . Select ( p => p . type ) . ToArray ( ) ) ;
369370 invokeBuilder . SetImplementationFlags ( MethodImplAttributes . Runtime | MethodImplAttributes . Managed ) ;
371+ var invokeReturnParam = invokeBuilder . DefineParameter ( 0 , functionSignature . returnParameter . parameterAttributes , null ) ;
372+ foreach ( var attr in functionSignature . returnParameter . customAttributes )
373+ {
374+ invokeReturnParam . SetCustomAttribute ( GetAttributeBuilderFromAttributeInstance ( attr ) ) ;
375+ }
376+ for ( int i = 0 ; i < functionSignature . parameters . Length ; i ++ )
377+ {
378+ var param = functionSignature . parameters [ i ] ;
379+ var paramBuilder = invokeBuilder . DefineParameter ( i + 1 , param . parameterAttributes , null ) ;
380+ foreach ( var attr in param . customAttributes )
381+ {
382+ paramBuilder . SetCustomAttribute ( GetAttributeBuilderFromAttributeInstance ( attr ) ) ;
383+ }
384+ }
370385
371386 _createdDelegateTypes ++ ;
372387 return delBuilder . CreateType ( ) ;
373388 }
374389
390+ private static CustomAttributeBuilder GetAttributeBuilderFromAttributeInstance ( Attribute attribute )
391+ {
392+ var attrType = attribute . GetType ( ) ;
393+ switch ( attribute )
394+ {
395+ case MarshalAsAttribute marshalAsAttribute :
396+ {
397+ var ctor = attrType . GetConstructor ( MARSHAL_AS_ATTRIBUTE_CTOR_PARAMETERS ) ;
398+ object [ ] ctorArgs = { marshalAsAttribute . Value } ;
399+ var fields = attrType . GetFields ( BindingFlags . Public | BindingFlags . Instance )
400+ . Where ( f => f . FieldType . IsValueType ) . ToArray ( ) ; //XXX: Used to bypass Mono bug, see https://github.com/mono/mono/issues/12747
401+ var fieldArgumentValues = new object [ fields . Length ] ;
402+ for ( int i = 0 ; i < fields . Length ; i ++ )
403+ {
404+ fieldArgumentValues [ i ] = fields [ i ] . GetValue ( attribute ) ;
405+ }
406+
407+ //MarshalAsAttribute has no properties other than Value, which is passed in constructor, hence empty properties array
408+ return new CustomAttributeBuilder ( ctor , ctorArgs , Array . Empty < PropertyInfo > ( ) , Array . Empty < object > ( ) ,
409+ fields , fieldArgumentValues ) ;
410+ }
411+ case InAttribute _:
412+ {
413+ var ctor = attrType . GetConstructor ( Type . EmptyTypes ) ;
414+ return new CustomAttributeBuilder ( ctor , Array . Empty < object > ( ) , Array . Empty < PropertyInfo > ( ) , Array . Empty < object > ( ) ,
415+ Array . Empty < FieldInfo > ( ) , Array . Empty < object > ( ) ) ;
416+ }
417+ case OutAttribute _:
418+ {
419+ var ctor = attrType . GetConstructor ( Type . EmptyTypes ) ;
420+ return new CustomAttributeBuilder ( ctor , Array . Empty < object > ( ) , Array . Empty < PropertyInfo > ( ) , Array . Empty < object > ( ) ,
421+ Array . Empty < FieldInfo > ( ) , Array . Empty < object > ( ) ) ;
422+ }
423+ default :
424+ throw new NotImplementedException ( $ "Attribute { attrType } is not supported") ;
425+ }
426+ }
375427
376428 private static string GetDllPath ( string dllName )
377429 {
0 commit comments