编译时不知道DLL文件时如何使用PInvoke?

8

我正在尝试在C#中使用PInvoke调用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的名称,我就不会有任何问题,代码可能看起来像这样:something

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

我应该如何在不知道编译时加载的dll的情况下完成这个操作?
3个回答

7
你需要按照相同的方式进行操作。声明一个与导出函数签名匹配的委托类型,就像SomeFuncSig一样。使用PInvoke LoadLibrary和GetProcAddress获取导出函数的IntPtr,就像在C ++中所做的那样。然后使用Marshal.GetDelegateForFunctionPointer()创建委托对象。

5

1
我有什么遗漏吗?要使用LoadLibrary,您确实需要知道dll的名称。如果OP“知道” dll的名称,他就不会首先尝试找到其他解决方案。编辑:我想我错过了“在编译时”与“在运行时”的区别。 - Sascha Hennig

1
如果您事先知道DLL名称和函数名称,则有一种更简单的方法。
您可以简单地声明P / Invoke签名,然后使用LoadLibrary根据例如配置文件条目加载DLL。只要在使用任何P / Invoke函数之前成功调用LoadLibrary,它们将成功,因为DLL已经加载。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接