moel@165: /* moel@165: moel@344: This Source Code Form is subject to the terms of the Mozilla Public moel@344: License, v. 2.0. If a copy of the MPL was not distributed with this moel@344: file, You can obtain one at http://mozilla.org/MPL/2.0/. moel@165: moel@384: Copyright (C) 2009-2012 Michael Möller moel@344: moel@165: */ moel@165: moel@165: using System; moel@165: using System.Collections.Generic; moel@165: using System.Reflection; moel@165: using System.Reflection.Emit; moel@165: using System.Runtime.InteropServices; moel@384: using OpenHardwareMonitor.Collections; moel@165: moel@165: namespace OpenHardwareMonitor.Hardware { moel@165: moel@195: internal static class PInvokeDelegateFactory { moel@165: moel@195: private static readonly ModuleBuilder moduleBuilder = moel@167: AppDomain.CurrentDomain.DefineDynamicAssembly( moel@167: new AssemblyName("PInvokeDelegateFactoryInternalAssembly"), moel@167: AssemblyBuilderAccess.Run).DefineDynamicModule( moel@167: "PInvokeDelegateFactoryInternalModule"); moel@165: moel@384: private static readonly IDictionary, Type> wrapperTypes = moel@384: new Dictionary, Type>(); moel@165: moel@165: public static void CreateDelegate(DllImportAttribute dllImportAttribute, moel@165: out T newDelegate) where T : class moel@165: { moel@165: Type wrapperType; moel@384: Pair key = moel@384: new Pair(dllImportAttribute, typeof(T)); moel@384: wrapperTypes.TryGetValue(key, out wrapperType); moel@165: moel@165: if (wrapperType == null) { moel@165: wrapperType = CreateWrapperType(typeof(T), dllImportAttribute); moel@384: wrapperTypes.Add(key, wrapperType); moel@165: } moel@165: moel@165: newDelegate = Delegate.CreateDelegate(typeof(T), wrapperType, moel@165: dllImportAttribute.EntryPoint) as T; moel@165: } moel@165: moel@165: moel@165: private static Type CreateWrapperType(Type delegateType, moel@165: DllImportAttribute dllImportAttribute) { moel@165: moel@165: TypeBuilder typeBuilder = moduleBuilder.DefineType( moel@165: "PInvokeDelegateFactoryInternalWrapperType" + wrapperTypes.Count); moel@165: moel@165: MethodInfo methodInfo = delegateType.GetMethod("Invoke"); moel@165: moel@165: ParameterInfo[] parameterInfos = methodInfo.GetParameters(); moel@165: int parameterCount = parameterInfos.GetLength(0); moel@165: moel@165: Type[] parameterTypes = new Type[parameterCount]; moel@165: for (int i = 0; i < parameterCount; i++) moel@165: parameterTypes[i] = parameterInfos[i].ParameterType; moel@165: moel@165: MethodBuilder methodBuilder = typeBuilder.DefinePInvokeMethod( moel@165: dllImportAttribute.EntryPoint, dllImportAttribute.Value, moel@165: MethodAttributes.Public | MethodAttributes.Static | moel@165: MethodAttributes.PinvokeImpl, CallingConventions.Standard, moel@165: methodInfo.ReturnType, parameterTypes, moel@165: dllImportAttribute.CallingConvention, moel@165: dllImportAttribute.CharSet); moel@165: moel@165: foreach (ParameterInfo parameterInfo in parameterInfos) moel@165: methodBuilder.DefineParameter(parameterInfo.Position + 1, moel@165: parameterInfo.Attributes, parameterInfo.Name); moel@165: moel@165: if (dllImportAttribute.PreserveSig) moel@165: methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig); moel@165: moel@165: return typeBuilder.CreateType(); moel@165: } moel@165: } moel@165: }