/// <summary> /// Link delegates fields using import declarations. /// </summary> /// <param name="path"> /// A <see cref="String"/> that specifies the assembly file path containing the import functions. /// </param> /// <param name="functionContext"> /// A <see cref="FunctionContext"/> mapping a <see cref="MethodInfo"/> with the relative function name. /// </param> /// <param name="function"> /// A <see cref="FieldInfo"/> that specifies the underlying function field to be updated. /// </param> /// <param name="getAddress"> /// A <see cref="GetAddressDelegate"/> used for getting function pointers. This parameter is dependent on the currently running platform. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="path"/>, <paramref name="function"/> or <paramref name="getAddress"/> is null. /// </exception> private static void BindAPIFunction(string path, FunctionContext functionContext, FieldInfo function, GetAddressDelegate getAddress) { if (path == null) { throw new ArgumentNullException("path"); } if (functionContext == null) { throw new ArgumentNullException("functionContext"); } if (function == null) { throw new ArgumentNullException("function"); } if (getAddress == null) { throw new ArgumentNullException("getAddress"); } Attribute[] aliasOfAttributes = Attribute.GetCustomAttributes(function, typeof(AliasOfAttribute)); string importName = function.Name.Substring(1); // Delegate name always prefixes with 'p' IntPtr importAddress = IntPtr.Zero; // Manages aliases (load external symbol) if (aliasOfAttributes.Length > 0) { for (int i = 0; i < aliasOfAttributes.Length; i++) { AliasOfAttribute aliasOfAttribute = (AliasOfAttribute)aliasOfAttributes[i]; if ((importAddress = getAddress(path, aliasOfAttribute.SymbolName)) != IntPtr.Zero) { break; } } } else { importAddress = getAddress(path, importName); } if (importAddress != IntPtr.Zero) { Delegate delegatePtr; // Try to load external symbol if ((delegatePtr = Marshal.GetDelegateForFunctionPointer(importAddress, function.FieldType)) == null) { MethodInfo methodInfo; if (functionContext.Imports.TryGetValue(importName, out methodInfo) == true) { delegatePtr = Delegate.CreateDelegate(function.FieldType, methodInfo); } } if (delegatePtr != null) { function.SetValue(null, delegatePtr); } } else { function.SetValue(null, null); // Function not implemented } }
/// <summary> /// Link delegates fields using import declarations. /// </summary> /// <param name="path"> /// A <see cref="String"/> that specifies the assembly file path containing the import functions. /// </param> /// <param name="getAddress"> /// A <see cref="GetAddressDelegate"/> used for getting function pointers. This parameter is dependent on the currently running platform. /// </param> /// <param name="functionContext"> /// A <see cref="FunctionContext"/> mapping a <see cref="MethodInfo"/> with the relative function name. /// </param> /// <param name="function"> /// A <see cref="FieldInfo"/> that specifies the underlying function field to be updated. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="path"/>, <paramref name="function"/> or <paramref name="getAddress"/> is null. /// </exception> private static void BindAPIFunction(string path, GetAddressDelegate getAddress, FunctionContext functionContext, FieldInfo function, KhronosVersion version, ExtensionsCollection extensions) { if (path == null) { throw new ArgumentNullException("path"); } if (functionContext == null) { throw new ArgumentNullException("functionContext"); } if (function == null) { throw new ArgumentNullException("function"); } if (getAddress == null) { throw new ArgumentNullException("getAddress"); } if (version != null || extensions != null) { if (IsCompatibleField(function, version, extensions) == false) { function.SetValue(null, null); // Function not supported: reset return; } } string importName = function.Name.Substring(1); // Delegate name always prefixes with 'p' IntPtr importAddress = IntPtr.Zero; // Load command address importAddress = getAddress(path, importName); // Manages aliases (load external symbol) if (importAddress == IntPtr.Zero) { #if !NETCORE Attribute[] aliasOfAttributes = Attribute.GetCustomAttributes(function, typeof(AliasOfAttribute)); #else Attribute[] aliasOfAttributes = new List <Attribute>(function.GetCustomAttributes(typeof(AliasOfAttribute))).ToArray(); #endif for (int i = 1 /* Skip base name */; i < aliasOfAttributes.Length; i++) { AliasOfAttribute aliasOfAttribute = (AliasOfAttribute)aliasOfAttributes[i]; if ((importAddress = getAddress(path, aliasOfAttribute.SymbolName)) != IntPtr.Zero) { break; } } } if (importAddress != IntPtr.Zero) { Delegate delegatePtr; // Try to load external symbol if ((delegatePtr = Marshal.GetDelegateForFunctionPointer(importAddress, function.FieldType)) == null) { MethodInfo methodInfo; if (functionContext.Imports.TryGetValue(importName, out methodInfo) == true) { #if !NETCORE delegatePtr = Delegate.CreateDelegate(function.FieldType, methodInfo); #else delegatePtr = methodInfo.CreateDelegate(function.FieldType); #endif } } if (delegatePtr != null) { function.SetValue(null, delegatePtr); } } else { function.SetValue(null, null); // Function not implemented: reset } }