[英]Is there any way to load a 32-bit DLL from managed 64-bit code without downgrading the managed code to 32-bit?
[英]32 or 64 bit DLL loading from .Net managed code
我有一個非托管DLL(Scintilla代碼編輯器的scilexer.dll,由CodePlex的Scintilla.Net使用),它是通過Scintilla.Net組件從托管應用程序加載的。 Windows托管應用程序在32位和64位環境中運行沒有問題,但我需要創建使用64或32 scilexer.dll的不同安裝。
有沒有辦法以32位和64位格式分發這兩個DLL,以便.Net框架的DLL加載器加載32或64位格式的非托管DLL,具體取決於某些.config選項或一些“路徑名稱魔術”的東西?
P / Invoke使用LoadLibrary加載DLL,如果已經加載了給定名稱的庫,LoadLibrary將返回它。 因此,如果您可以為這兩個版本的DLL提供相同的名稱,但將它們放在不同的目錄中,您可以在第一次從scilexer.dll調用函數之前執行此類操作,而無需復制您的extern聲明:
string platform = IntPtr.Size == 4 ? "x86" : "x64";
string dll = installDir + @"\lib-" + platform + @"\scilexer.dll";
if (LoadLibrary(dll) == IntPtr.Zero)
throw new IOException("Unable to load " + dll + ".");
不幸的是,我對這個特定的DLL一無所知。 但是,當您自己進行P / Invoke,並且可以處理一些重復時,可以為每個平台創建一個代理。
例如,假設您有以下接口,應該由32位或64位DLL實現:
public interface ICodec {
int Decode(IntPtr input, IntPtr output, long inputLength);
}
您創建代理:
public class CodecX86 : ICodec {
private const string dllFileName = @"Codec.x86.dll";
[DllImport(dllFileName)]
static extern int decode(IntPtr input, IntPtr output, long inputLength);
public int Decode(IntPtr input, IntPtr output, long inputLength) {
return decode(input, output, inputLength);
}
}
和
public class CodecX64 : ICodec {
private const string dllFileName = @"Codec.x64.dll";
[DllImport(dllFileName)]
static extern int decode(IntPtr input, IntPtr output, long inputLength);
public int Decode(IntPtr input, IntPtr output, long inputLength) {
return decode(input, output, inputLength);
}
}
最后建立一個為您選擇合適的工廠:
public class CodecFactory {
ICodec instance = null;
public ICodec GetCodec() {
if (instance == null) {
if (IntPtr.Size == 4) {
instance = new CodecX86();
} else if (IntPtr.Size == 8) {
instance = new CodecX64();
} else {
throw new NotSupportedException("Unknown platform");
}
}
return instance;
}
}
由於DLL在第一次被調用時被懶惰地加載,這實際上是有效的,盡管每個平台只能加載原生的版本。 有關更詳細的說明,請參閱此文章 。
我提出的最好的是以下內容:
File.Delete(Application.StartupPath + @"\scilexer.dll"); { // Check for 64 bit and copy the proper scilexer dll if (IntPtr.Size == 4) { File.Copy(Application.StartupPath + @"\scilexer32.dll", Application.StartupPath + @"\scilexer.dll"); } else { File.Copy(Application.StartupPath + @"\scilexer64.dll", Application.StartupPath + @"\scilexer.dll"); } }
您可以將dll放在system32中。 syswow64中的32位和實際system32中的64位。 對於32位應用程序,當訪問system32時,它們被重定向到Syswow64。
您可以在注冊表中創建一個條目。 軟件密鑰有一個名為Wow6432Node的子項,32位應用程序將其視為軟件密鑰。
非托管dll可以與其管理對應方並排安裝到GAC中。 本文應解釋它是如何工作的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.