Gil*_*lad 59 .net c# pinvoke dllimport 32bit-64bit
这是情况,我在我的dot.net应用程序中使用基于C的dll.有2个dll,一个是32位称为MyDll32.dll,另一个是64位版本,名为MyDll64.dll.
有一个保存DLL文件名的静态变量:string DLL_FILE_NAME.
它以下列方式使用:
[DllImport(DLL_FILE_NAME, CallingConvention=CallingConvention.Cdecl, EntryPoint=Func1")]
private static extern int is_Func1(int var1, int var2);
Run Code Online (Sandbox Code Playgroud)
到目前为止简单.
可以想象,该软件是在打开"Any CPU"的情况下编译的.
我还有以下代码来确定系统是否应该使用64位文件或32位文件.
#if WIN64
public const string DLL_FILE_NAME = "MyDll64.dll";
#else
public const string DLL_FILE_NAME = "MyDll32.dll";
#endif
Run Code Online (Sandbox Code Playgroud)
到目前为止,您应该看到问题.. DLL_FILE_NAME是在编译时定义的,而不是在执行时间中定义的,因此根据执行上下文不会加载右dll.
处理这个问题的正确方法是什么?我不想要两个执行文件(一个用于32位,另一个用于64位)?如何在DllImport语句中使用DLL_FILE_NAME 之前设置它?
Jul*_*ain 56
我发现最简单的方法是使用不同的名称导入两个方法,并调用正确的方法.在调用之前不会加载DLL所以它很好:
[DllImport("MyDll32.dll", EntryPoint = "Func1", CallingConvention = CallingConvention.Cdecl)]
private static extern int Func1_32(int var1, int var2);
[DllImport("MyDll64.dll", EntryPoint = "Func1", CallingConvention = CallingConvention.Cdecl)]
private static extern int Func1_64(int var1, int var2);
public static int Func1(int var1, int var2) {
return IntPtr.Size == 8 /* 64bit */ ? Func1_64(var1, var2) : Func1_32(var1, var2);
}
Run Code Online (Sandbox Code Playgroud)
当然,如果你有很多进口,手动维护可能会非常麻烦.
Ben*_*hon 54
这是另一种替代方案,要求两个DLL具有相同的名称并放在不同的文件夹中.例如:
win32/MyDll.dll
win64/MyDll.dll
诀窍是LoadLibrary
在CLR执行之前手动加载DLL .然后它会看到a MyDll.dll
已经加载并使用它.
这可以在父类的静态构造函数中轻松完成.
static class MyDll
{
static MyDll()
{
var myPath = new Uri(typeof(MyDll).Assembly.CodeBase).LocalPath;
var myFolder = Path.GetDirectoryName(myPath);
var is64 = IntPtr.Size == 8;
var subfolder = is64 ? "\\win64\\" : "\\win32\\";
LoadLibrary(myFolder + subfolder + "MyDll.dll");
}
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("MyDll.dll")]
public static extern int MyFunction(int var1, int var2);
}
Run Code Online (Sandbox Code Playgroud)
编辑2017/02/01:使用Assembly.CodeBase
即使启用了Shadow Copying也能正常工作.
小智 15
在这种情况下,我应该这样做(制作2个文件夹,x64和x86 +将相应的dll,同名,放在两个文件夹中):
using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
class Program {
static void Main(string[] args) {
var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
path = Path.Combine(path, IntPtr.Size == 8 ? "x64" : "x86");
bool ok = SetDllDirectory(path);
if (!ok) throw new System.ComponentModel.Win32Exception();
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetDllDirectory(string path);
}
Run Code Online (Sandbox Code Playgroud)
有一个保存DLL文件名的静态变量
它不是静态变量.在编译时它是一个常量.您无法在运行时更改编译时常量.
处理这个问题的正确方法是什么?
老实说,我建议只针对x86并忘记64位版本,让你的应用程序在WOW64上运行,除非你的应用程序迫切需要以x64运行.
如果需要x64,您可以:
将DLL更改为具有相同的名称,例如MyDll.dll
,在安装/部署时,将正确的DLL 放在适当的位置.(如果操作系统是x64,则部署64位版本的DLL,否则部署x86版本).
有两个单独的版本,一个用于x86,另一个用于x64.
归档时间: |
|
查看次数: |
46884 次 |
最近记录: |