【问题标题】:How to load dll dynamically and pass/get value to it?如何动态加载 dll 并向其传递/获取值?
【发布时间】:2018-02-25 02:58:14
【问题描述】:

DllImport 我可以这样做:

[DllImport(".../Desktop/Calculate.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int Sub(int a, int b);

但我想决定在运行时加载哪个 dll。 所以我没有使用DllImport,但试试这个:

using System;
using System.Runtime.InteropServices;

namespace TestCall   
{
    class Program
    {
        [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
        static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
        static extern IntPtr GetProcAddress(int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
        static extern bool FreeLibrary(int hModule);
        delegate void CallMethod();
        static void Main(string[] arg)  //pass in string array
        {
            string DllName = ".../Desktop/Calculate.dll";  //would be like: string  DllName = ChooseWhatDllToCall();
            string FuncName = "Sub";                       //would be like: string FuncName = ChooseWhatFuncToUse();
            int hModule = LoadLibrary(DllName); // you can build it dynamically 
            if (hModule == 0) return;
            IntPtr intPtr;
            CallMethod action;

            intPtr = GetProcAddress(hModule, FuncName);
            action = (CallMethod)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(CallMethod));
            action.Invoke();
        }
    }
}

但是我如何将Sub 定义为int Sub(int a, int b);,就像我使用DllImport 一样?

【问题讨论】:

    标签: c# dll dllimport loadlibrary getprocaddress


    【解决方案1】:

    您可以按如下方式定义委托:

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate Int32 Sub(Int32 a, Int32 b);
    

    然后,在您的代码中:

    Sub sub = (Sub)Marshal.GetDelegateForFunctionPointer(intPtr,typeof(Sub));
    
    Int32 a = 5;
    Int32 b = 8;
    Int32 result = sub(a, b);
    

    【讨论】:

      【解决方案2】:

      如果您需要 dll 中的多个功能,您应该希望在此过程中实现自动化。在一个电话中获得代表真是太好了,例如:

      IntPtr hModule = LoadLibrary(".../MyLibrairy.dll"); 
      var sub = DelegateBuilder<Sub>(hModule, "Sub");
      var result = sub((Int32)5, (Int32)8);
      

      就是这样:

      public static T DelegateBuilder<T>(IntPtr loadedDLL, string delegateName = null) where T : Delegate
      {
          string functionName = delegateName ?? typeof(T).ToString().Split('+').Last();
          IntPtr pAddressOfFunctionToCall = GetProcAddress(loadedDLL, functionName);
          if (pAddressOfFunctionToCall == IntPtr.Zero)
          {
              var errorMessage = string.Format("Not found function <{0}> in dll ", functionName);
              throw new EntryPointNotFoundException(errorMessage);
          }
          T functionDelegate = Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(T)) as T;
          return functionDelegate;
      }
      

      有可能直接调用结果,代码不可读:

      var result = DelegateBuilder<Sub>(hModule)((Int32)5, (Int32)8);
      

      对以上代码的任何评论将不胜感激 特别感谢 (Damien.B:)

      【讨论】:

        猜你喜欢
        • 2015-01-13
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 1970-01-01
        • 2011-09-06
        • 2021-03-19
        • 1970-01-01
        • 2016-03-08
        相关资源
        最近更新 更多