我有一個應用程序構建爲'任何CPU',並有相同的庫的兩個第三方Dll針對x86和x64。我想在運行時包含這些庫中的一個,具體取決於它在客戶機上運行的平臺。最好的辦法是什麼?根據平臺加載x64或x86 DLL?
回答
如果我們談論的是託管DLL,申報P /調用是這樣的:
[DllImport("DllName.dll")]
static extern foo();
請注意,我們沒有指定的DLL,只是它的名字,這是我設定一個路徑是相同的32位和64位版本。
然後,在調用任何p/invokes之前,將庫加載到您的進程中。通過p /調用到LoadLibrary
API函數來完成此操作。此時,您將確定您的進程是32位還是64位,並相應地構建DLL的完整路徑。完整的路徑是你通過LoadLibrary
。
現在,當您調用庫的p/invokes時,它們將由您剛加載的模塊解析。
對於託管程序集,則可以使用Assembly.LoadFile
來指定程序集的路徑。這可能是一個棘手的編排,但這篇優秀的文章告訴你如何:Automatically Choose 32 or 64 Bit Mixed Mode DLLs。有很多與混合模式相關的細節以及可能與您無關的本機DLL依賴關係。關鍵是AppDomain.CurrentDomain.AssemblyResolve
事件處理程序。
我其實對這個主題很有經驗,所以我想我會根據我在鉛筆遊戲中使用的方式發佈答案。首先,你需要「DllImport
」兩個函數,一個來自32位dll,另一個來自64位dll(或者dylib,無論你的平臺使用什麼)。
static class Foo32 {
[DllImport("32bitdll.dll")]
internal static extern void Foo();
}
static class Foo64 {
[DllImport("64bitdll.dll")]
internal static extern void Foo();
}
然後,你需要含有代表一箇中間類,並且從32位或64位的互操作導入它們根據IntPtr
的大小(我不使用Environment.Is64BitProcess
,因爲這是一個.NET 4功能) :
internal delegate void FooDelegate();
static class FooDelegates {
internal static FooDelegate Foo;
static FooDelegates() {
Type interop = (IntPtr.Size == 8) ? typeof(Foo64) : typeof(Foo32);
FieldInfo[] fields = typeof(FooDelegates).GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
foreach (FieldInfo fi in fields) {
MethodInfo mi = glfwInterop.GetMethod(fi.Name, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
Delegate function = Delegate.CreateDelegate(fi.FieldType, mi);
fi.SetValue(null, function);
}
}
}
然後我通常使用一個「真正的」類,包含你輸入(儘管這在技術上並不需要)功能:
public static class FooApi {
public static void Foo() {
FooDelegates.Foo();
}
}
如果您只需要一個或兩個函數,這是一個真正的痛苦,但導入代表的方式對於大型庫/應用程序非常有效。你可能想看看github上的Pencil.Gaming,因爲它使用這種方法相當廣泛(here是一個很多使用它的例子)。
此方法的另一個好處是它是100%的跨平臺,並且不依賴任何WinAPI函數。
你不需要任何代表。對於所有導入的函數,您可以使用普通的舊'DllImport'來完成整個任務。 –
@DavidHeffernan但是,你不能使用「任何CPU」。然後,您需要爲32位和64位系統重新分配您的應用程序的單獨版本。 – antonijn
確定您可以使用AnyCPU。我的答案解釋瞭如何。您確實需要這些DLL才能擁有相同的名稱,但在不同的文件夾中您會注意到這一點。但對於32/64位的DLL,這是正常的。 –
我對我的問題的完整解決方案是使用David Heffernan提供的第二個鏈接。 我所做的是 1.引用了項目中的虛擬dll。 2.指定的兩個預生成事件
xcopy /y "$(SolutionDir)\Assemblies\Lib\x86\(Assembly name)*" "$(TargetDir)"
xcopy /y "$(SolutionDir)\Assemblies\Lib\x64\(Assemble name)*" "$(TargetDir)"
3和裝配中解決事件的應用程序的啓動改變取決於平臺對應的彙編。
var currentDomain = AppDomain.CurrentDomain;
var location = Assembly.GetExecutingAssembly().Location;
var assemblyDir = Path.GetDirectoryName(location);
if (assemblyDir != null && (File.Exists(Path.Combine(assemblyDir, "(Assembly name).proxy.dll"))
|| !File.Exists(Path.Combine(assemblyDir, "(Assembly name).x86.dll"))
|| !File.Exists(Path.Combine(assemblyDir, "(Assembly name).x64.dll"))))
{
throw new InvalidOperationException("Found (Assembly name).proxy.dll which cannot exist. "
+ "Must instead have (Assembly name).x86.dll and (Assembly name).x64.dll. Check your build settings.");
}
currentDomain.AssemblyResolve += (sender, arg) =>
{
if (arg.Name.StartsWith("(Assembly name),", StringComparison.OrdinalIgnoreCase))
{
string fileName = Path.Combine(assemblyDir,
string.Format("(Assembly).{0}.dll", (IntPtr.Size == 4) ? "x86" : "x64"));
return Assembly.LoadFile(fileName);
}
return null;
};
但是,這隻適用於.net dll,不適用於任何DLL – Tyron
- 1. Visual Studio加載正確的(x86或x64)dll!
- 2. 加載x86或x64程序集
- 3. Visual Studio MVC平臺 - x86和x64?
- 4. $(var.Platform)在x64平臺上給x86?
- 5. 無法同時使用emgu CV爲x86平臺加載DLL cvextern
- 6. JAVA SE x86或x64?
- 7. 在構建C#項目時有visual studio copy x64 DLL或x86 DLL
- 8. 平臺目標(x86/x64/AnyCPU)對於純託管.NET dll是否重要?
- 9. 在Visual Studio 2012中同時運行平臺目標x86和x64
- 10. 如何根據客戶端體系結構動態加載SQLite3.DLL的x86/x64版本?
- 11. x86或x64反彙編LIB
- 12. 對於x64平臺
- 13. 使用平臺屬性構建WiX x86/x64
- 14. 如何在x86/x64平臺上運行MIPS二進制文件?
- 15. C#.NET x86/x64哪個項目決定平臺?
- 16. 在x64操作系統/平臺上運行x86 msi設置
- 17. 確定是否x86或x64系統
- 18. Apache x86和PHP x64
- 19. 注入x64進程的x64-DLL掛鉤x86-DLL失敗,使用C++和EasyHook
- 20. 任何CPU平臺和X86平臺
- 21. 使用並行程序集加載DLL的x64或x32版本
- 22. RXTX x64和x86
- 23. FASM - x64與x86
- 24. Win32和x64平臺命名
- 25. 兩個x64和x86環境
- 26. 爲什麼visual studio在64位平臺上鍊接MSVCR90.dll(x86)?
- 27. MSBuild。使用x86,x64和任何CPU平臺構建解決方案
- 28. x86彙編學習平臺
- 29. 從MSBuild啓動x86或x64 MSI bootstrapper - newb
- 30. x64 vs x86 for CUDA
這些託管程序集或本機代碼? –
爲什麼你不想構建應用程序的x86和x64版本? – outcoldman
我想說他們是混合的。反編譯給了我很多用C編寫的代碼,但我仍然不確定。 – Ammark