我今天问了这个问题,但它被错误地关闭了,我无法选择重新打开它。因此,我不得不再问一遍。
我有一个类,其中有一长串定义,如下所示:
[DllImport(NativeLibraryName, EntryPoint = "FunctionName", CallingConvention = CallingConvention.Cdecl)]
public static extern void FunctionName();
参数“NativeLibraryName”由编译器开关设置。但是,我想在运行时设置此参数。我的问题是,我需要考虑两种不同的 DLL:一种用于 32 位系统,一种用于 64 位系统,并且它们的名称不同。我想要实现的是确定应用程序是否以 64 位或 32 位运行并使用正确的 DLL。我需要加载正确的 DLL,否则我会遇到 BadImageFormatExceptions。
切换为代表
我可以使用 Reflection 生成一个文件,其功能与使用委托给出的文件相同像这样。在这里,我可以在运行时提供正确的 DLL 的路径。
重命名 DLL
我还可以重命名这两个 DLL,使它们具有相同的名称,但将它们放在不同的目录中。然后我可以选择要从中加载 DLL 的文件夹。
这两个选项都可以正常工作,但我正在处理的项目是现有项目的一个分支,我希望尽可能少地进行更改,以便我可以轻松地将原始项目的更新合并到我的项目中。
我很高兴你的任何想法。
这个线程被错误地建议作为我的问题的解决方案,并且原始线程在那之后被关闭。该线程讨论了类似的问题,但它没有提供适用于我的问题的解决方案。事实上,实际上提出了我自己想出的解决方案之一,但我正在寻找更好的方法来做到这一点。
一个简单的方法是确保 DLL 具有相同的文件名(例如MyNativeLibrary.dll
)并将它们存储在单独的子文件夹中,例如:
-
x86\MyNativeLibrary.dll
对于 32 位 DLL
-
x64\MyNativeLibrary.dll
对于 64 位 DLL
声明 P/Invoke 方法时,您可以使用库的名称,而不指定硬编码路径,例如:
public static class MyUtilityClass
{
[DllImport("MyNativeLibrary.dll")]
public static extern int DoSomething(int x, int y);
}
最后,如果您的应用程序在开始时使用NativeLibrary.Load(string)传入您要加载的 DLL 的完整路径。这是必须要做的before尝试调用 DLL 的任何函数。
// Pseudo-code. You might need to adapt to find the path where your DLLs are located
// Get the folder path where the current `App.exe` is located
var startupPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule?.FileName);
// Assume the DLL is in a sub-folder of the folder where `App.exe` is located
var myLibraryFullPath = Environment.Is64BitProcess
? Path.Combine(startupPath, @"x64\MyNativeLibrary.dll")
: Path.Combine(startupPath, @"x86\MyNativeLibrary.dll");
// Load the appropriate DLL into the current process
NativeLibrary.Load(myLibraryFullPath);
一旦非托管 DLL 加载到进程中,任何未来的 P/Invokes 都会用[DllImport("MyNativeLibrary.dll")]
将绑定到已经加载的 DLL,这就是它起作用的原因。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)