1

In DllImport I can do this:

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

But I want to decide which dll to load at run time. So I'm not using DllImport but try this:

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();
        }
    }
}

But how can I define Sub as int Sub(int a, int b); like I'm using DllImport?

4

2 回答 2

2

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

[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);
于 2018-02-25T03:03:29.537 回答
0

如果您需要 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:)

于 2019-10-16T09:40:28.040 回答