Hardware/PInvokeDelegateFactory.cs
author sl
Sun, 03 Feb 2013 18:01:50 +0100
changeset 391 ca4c0e7ae75d
parent 344 3145aadca3d2
permissions -rw-r--r--
Converted project to VisualStudio 2012.
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
moel@165
     1
/*
moel@165
     2
 
moel@344
     3
  This Source Code Form is subject to the terms of the Mozilla Public
moel@344
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@165
     6
 
moel@384
     7
  Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
	
moel@165
     9
*/
moel@165
    10
moel@165
    11
using System;
moel@165
    12
using System.Collections.Generic;
moel@165
    13
using System.Reflection;
moel@165
    14
using System.Reflection.Emit;
moel@165
    15
using System.Runtime.InteropServices;
moel@384
    16
using OpenHardwareMonitor.Collections;
moel@165
    17
moel@165
    18
namespace OpenHardwareMonitor.Hardware {
moel@165
    19
moel@195
    20
  internal static class PInvokeDelegateFactory {
moel@165
    21
moel@195
    22
    private static readonly ModuleBuilder moduleBuilder = 
moel@167
    23
      AppDomain.CurrentDomain.DefineDynamicAssembly(
moel@167
    24
        new AssemblyName("PInvokeDelegateFactoryInternalAssembly"),
moel@167
    25
        AssemblyBuilderAccess.Run).DefineDynamicModule(
moel@167
    26
        "PInvokeDelegateFactoryInternalModule");
moel@165
    27
moel@384
    28
    private static readonly IDictionary<Pair<DllImportAttribute, Type>, Type> wrapperTypes =
moel@384
    29
      new Dictionary<Pair<DllImportAttribute, Type>, Type>();
moel@165
    30
moel@165
    31
    public static void CreateDelegate<T>(DllImportAttribute dllImportAttribute,
moel@165
    32
      out T newDelegate) where T : class 
moel@165
    33
    {
moel@165
    34
      Type wrapperType;
moel@384
    35
      Pair<DllImportAttribute, Type> key =
moel@384
    36
        new Pair<DllImportAttribute, Type>(dllImportAttribute, typeof(T));
moel@384
    37
      wrapperTypes.TryGetValue(key, out wrapperType);
moel@165
    38
moel@165
    39
      if (wrapperType == null) {
moel@165
    40
        wrapperType = CreateWrapperType(typeof(T), dllImportAttribute);
moel@384
    41
        wrapperTypes.Add(key, wrapperType);
moel@165
    42
      }
moel@165
    43
moel@165
    44
      newDelegate = Delegate.CreateDelegate(typeof(T), wrapperType,
moel@165
    45
        dllImportAttribute.EntryPoint) as T;
moel@165
    46
    }
moel@165
    47
moel@165
    48
moel@165
    49
    private static Type CreateWrapperType(Type delegateType,
moel@165
    50
      DllImportAttribute dllImportAttribute) {
moel@165
    51
moel@165
    52
      TypeBuilder typeBuilder = moduleBuilder.DefineType(
moel@165
    53
        "PInvokeDelegateFactoryInternalWrapperType" + wrapperTypes.Count);
moel@165
    54
moel@165
    55
      MethodInfo methodInfo = delegateType.GetMethod("Invoke");
moel@165
    56
moel@165
    57
      ParameterInfo[] parameterInfos = methodInfo.GetParameters();
moel@165
    58
      int parameterCount = parameterInfos.GetLength(0);
moel@165
    59
moel@165
    60
      Type[] parameterTypes = new Type[parameterCount];
moel@165
    61
      for (int i = 0; i < parameterCount; i++)
moel@165
    62
        parameterTypes[i] = parameterInfos[i].ParameterType;
moel@165
    63
moel@165
    64
      MethodBuilder methodBuilder = typeBuilder.DefinePInvokeMethod(
moel@165
    65
        dllImportAttribute.EntryPoint, dllImportAttribute.Value,
moel@165
    66
        MethodAttributes.Public | MethodAttributes.Static |
moel@165
    67
        MethodAttributes.PinvokeImpl, CallingConventions.Standard,
moel@165
    68
        methodInfo.ReturnType, parameterTypes,
moel@165
    69
        dllImportAttribute.CallingConvention,
moel@165
    70
        dllImportAttribute.CharSet);
moel@165
    71
moel@165
    72
      foreach (ParameterInfo parameterInfo in parameterInfos)
moel@165
    73
        methodBuilder.DefineParameter(parameterInfo.Position + 1,
moel@165
    74
          parameterInfo.Attributes, parameterInfo.Name);
moel@165
    75
moel@165
    76
      if (dllImportAttribute.PreserveSig)
moel@165
    77
        methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
moel@165
    78
moel@165
    79
      return typeBuilder.CreateType();
moel@165
    80
    }
moel@165
    81
  }
moel@165
    82
}