2011-09-30 73 views
6

在C#中,我想的PInvoke一個「簡單」的功能,我在C++。問題是在編譯時我不知道庫的名稱或位置。在C++中,這很容易:PInvoke在編譯時不知道DLL嗎?

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?

回答

5

禰是這裏的解決方案:Dynamically calling an unmanaged dll from .NET (C#)(基於調用LoadLibrary/GetProcAddress的)

+0

我缺少的東西?要使用LoadLibrary,您*需要知道dll的名稱。如果OP _knew_ dll的名字,他不會嘗試在第一個地方找到不同的解決方案。編輯:認爲我錯過了「在編譯時」vs「在運行時」。 –

7

你做同樣的方式。聲明一個簽名與導出函數匹配的委託類型,就像SomeFuncSig一樣。 Pinvoke LoadLibrary和GetProcAddress來獲取導出函數的IntPtr,就像在C++中一樣。然後用Marshal.GetDelegateForFunctionPointer()創建委託對象。

1

如果你事先知道的DLL名稱,你事先知道函數的名字,還有一個更簡單的方法。

你可以簡單地聲明的P/Invoke簽名,然後使用LoadLibrary加載例如基於配置文件項中的DLL。只要您成功地調用LoadLibrary任何P的前/調用所使用的功能,他們會取得成功的DLL已經加載。