当你在编译时不知道DLL时PInvoke?

时间:2011-09-30 05:09:54

标签: c# pinvoke

在C#中,我正在尝试使用C ++中的“简单”函数。问题是我在编译时不知道库的名称或位置。在C ++中,这很容易:

typedef HRESULT (*SomeFuncSig)(int, IUnknown *, IUnknown **);

const char *lib = "someLib.dll";  // Calculated at runtime

HMODULE mod = LoadLibrary(lib);
SomeFuncSig func = (SomeFuncSig)GetProcAddress("MyMethod");

IUnknown *in = GetSomeParam();
IUnknown *out = NULL;
HRESULT hr = func(12345, in, &out);

// Leave module loaded to continue using foo.

对于我的生活,我无法弄清楚如何在C#中做到这一点。如果我知道dll名称,我就不会有任何麻烦,它会像这样看起来像

[DllImport("someLib.dll")]
uint MyMethod(int i,
              [In, MarshalAs(UnmanagedType.Interface)] IUnknown input, 
              [Out, MarshalAs(UnmanagedType.Interface)] out IUnknown output);

如果不知道我在编译时加载的dll怎么办呢?

3 个答案:

答案 0 :(得分:7)

你以同样的方式做到这一点。声明一个委托类型,其签名与导出的函数匹配,就像SomeFuncSig一样。 Pinvoke LoadLibrary和GetProcAddress获取导出函数的IntPtr,就像在C ++中一样。然后使用Marshal.GetDelegateForFunctionPointer()创建委托对象。

答案 1 :(得分:5)

这是一个解决方案:Dynamically calling an unmanaged dll from .NET (C#)(基于LoadLibrary / GetProcAddress)

答案 2 :(得分:1)

如果您事先知道DLL名称,并且事先知道了函数名称,则有一种更简单的方法。

您可以简单地声明P / Invoke签名,然后使用LoadLibrary根据配置文件条目加载DLL。只要您在使用任何P / Invoke函数之前成功调用LoadLibrary ,它们就会成功,因为已经加载了DLL。