Tôi có một ứng dụng được xây dựng dưới dạng 'Bất kỳ CPU' và có hai Dll của cùng một bên thứ ba của cùng một thư viện được nhắm mục tiêu đến x86 và x64. Tôi muốn bao gồm một trong các thư viện này trong thời gian chạy tùy thuộc vào nền tảng nó sẽ chạy trên máy khách. Điều gì sẽ là cách tốt nhất để đi về nó?Tải x64 hoặc x86 DLL tùy thuộc vào nền tảng?
Trả lời
Nếu chúng ta đang nói về DLL không được quản lý, khai báo p/gọi như thế này:
[DllImport("DllName.dll")]
static extern foo();
Lưu ý rằng chúng tôi không chỉ định một đường dẫn đến DLL, chỉ cần tên của nó, mà tôi đoán là như nhau cho cả phiên bản 32 bit và 64 bit.
Sau đó, trước khi bạn gọi bất kỳ p/invokes nào của bạn, hãy tải thư viện vào quá trình của bạn. Làm điều đó bằng cách p/gọi hàm LoadLibrary
API. Tại thời điểm này, bạn sẽ xác định xem quá trình của bạn là 32 hoặc 64 bit và xây dựng đường dẫn đầy đủ đến DLL cho phù hợp. Đường dẫn đầy đủ đó là những gì bạn chuyển đến LoadLibrary
.
Bây giờ, khi bạn gọi p/invokes cho thư viện, chúng sẽ được giải quyết bởi mô đun mà bạn vừa tải.
Đối với các hội đồng quản lý, bạn có thể sử dụng Assembly.LoadFile
để chỉ định đường dẫn của hội đồng. Điều này có thể là một chút khó khăn để dàn nhạc, nhưng bài viết tuyệt vời này cho bạn thấy làm thế nào: Automatically Choose 32 or 64 Bit Mixed Mode DLLs. Có rất nhiều chi tiết liên quan đến chế độ hỗn hợp và các phụ thuộc DLL gốc có thể không liên quan đến bạn. Điều quan trọng là trình xử lý sự kiện AppDomain.CurrentDomain.AssemblyResolve
.
Rất tuyệt. Tôi không biết điều này. – Ani
Cảm ơn David, Tôi có cần phải tạo một trình bao bọc xung quanh các dll hiện có, vì các phương pháp tôi cần truy cập không phải là tĩnh không? – Ammark
Bạn có sử dụng 'DllImport' ngay bây giờ khi bạn gọi mã của bạn khi bạn biên dịch giống như x86 hay chỉ x64? –
Tôi thực sự rất có kinh nghiệm về chủ đề này, vì vậy tôi nghĩ tôi sẽ đăng câu trả lời theo cách tôi đã sử dụng trong Pencil.Gaming. Thứ nhất, bạn phải "DllImport
" hai chức năng, một từ dll 32 bit và một từ 64-bit dll (hoặc như vậy, hoặc dylib, bất kỳ nền tảng nào của bạn sử dụng).
static class Foo32 {
[DllImport("32bitdll.dll")]
internal static extern void Foo();
}
static class Foo64 {
[DllImport("64bitdll.dll")]
internal static extern void Foo();
}
Sau đó, bạn cần một lớp trung gian có chứa các đại biểu, và nhập khẩu chúng từ interop 32 hoặc 64-bit theo kích thước của một IntPtr
(Tôi không sử dụng Environment.Is64BitProcess
, vì đó là một chức năng 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);
}
}
}
Và sau đó tôi thường sử dụng một lớp học "thật", chứa các chức năng bạn nhập khẩu (mặc dù điều này là không cần thiết về mặt kỹ thuật):
public static class FooApi {
public static void Foo() {
FooDelegates.Foo();
}
}
Đây là một nỗi đau thực sự nếu bạn chỉ cần một hoặc hai chức năng, nhưng cách nhập khẩu các đại biểu thực sự hiệu quả cho các thư viện/ứng dụng quy mô lớn hơn. Bạn có thể muốn kiểm tra Pencil.Gaming trên github, vì nó sử dụng phương pháp này khá rộng rãi (here là một ví dụ về nó được sử dụng rất nhiều).
Một lợi ích khác của phương pháp này là 100% nền tảng chéo và không dựa vào bất kỳ chức năng WinAPI nào.
Bạn không cần bất kỳ đại biểu nào. Bạn có thể thực hiện toàn bộ điều này với 'DllImport' cũ cho tất cả các hàm được nhập. –
@DavidHeffernan Nhưng sau đó bạn không thể sử dụng "CPU bất kỳ". Sau đó, bạn sẽ cần phải phân phối lại các phiên bản riêng biệt của ứng dụng của bạn cho các hệ thống 32 bit và 64 bit. – antonijn
Chắc chắn bạn có thể sử dụng AnyCPU. Câu trả lời của tôi giải thích như thế nào. Bạn cần các DLL để có cùng tên, nhưng ở trong các thư mục khác nhau, hãy nhớ đến bạn. Nhưng đó là điều bình thường đối với các tệp DLL có độ bit 32/64. –
Giải pháp hoàn chỉnh của tôi cho vấn đề của tôi là sử dụng liên kết thứ hai do David Heffernan cung cấp. Những gì tôi đã làm là 1. Tham chiếu một dll giả trong dự án. 2. rõ hai pre-build sự kiện
xcopy /y "$(SolutionDir)\Assemblies\Lib\x86\(Assembly name)*" "$(TargetDir)"
xcopy /y "$(SolutionDir)\Assemblies\Lib\x64\(Assemble name)*" "$(TargetDir)"
3. và khi khởi động của ứng dụng trong trường hợp lắp ráp quyết tâm thay đổi lắp ráp tương ứng phụ thuộc vào nền tảng này.
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;
};
Tuy nhiên, điều này chỉ hoạt động đối với dlls .net, không dành cho bất kỳ dll – Tyron
- 1. Visual Studio tải đúng (x86 hoặc x64) dll!
- 2. Đang tải x86 hoặc x64 assembly
- 3. Nền tảng giải pháp tích cực VS Nền tảng dự án VS Mục tiêu nền tảng
- 4. Biên dịch cho cả x86 và x64
- 5. mối quan hệ của tên "dự án win32" trong studio trực quan với nền tảng x86 hoặc x64
- 6. Sử dụng dll x64 trong ứng dụng x86
- 7. Thiết lập nhắm mục tiêu cả x86 và x64?
- 8. Gói VC + Redistributable nào để chọn (x86 hoặc x64)?
- 9. gcc generic march cho tất cả các nền tảng x64
- 10. Visual Studio: Cách tạo và chỉ định đúng cấu hình và nền tảng cho x64 và x86
- 11. Microsoft Fakes x64 không x86 và v4.5
- 12. Cố gắng không cần hai giải pháp riêng biệt cho chương trình x86 và x64
- 13. Cách tiêu chuẩn nhất để chọn tên hàm tùy thuộc vào nền tảng?
- 14. NET liên kết thư viện cụ nền tảng
- 15. làm thế nào để biết cpu để sử dụng trong xây dựng (x86 x64 hoặc AnyCpu)?
- 16. Làm thế nào hoặc tại sao MSBuild chọn nền tảng x64 khi tôi không chỉ định nó thay vì AnyCPU?
- 17. Entity Framework spinup chậm hơn trên x64 vs x86
- 18. x86/x64 Thêm Chuyển địa chỉ
- 19. biên dịch thư viện tĩnh C++ cho nền tảng Windows 64 bit bằng VS2008
- 20. Bizarre hành vi hành ternary trong trình gỡ lỗi trên nền tảng x64
- 21. Visual Studio 2012 bản địa C++ DLL biên dịch x86
- 22. Cách xử lý các gói x86 và x64
- 23. Plugin DLL phụ thuộc vào các tệp DLL khác
- 24. WiX: đăng ký thành phần .NET COM cả x86 x64
- 25. Ứng dụng x64 có thể sử dụng các cụm x86 - và ngược lại không?
- 26. Triển khai 32 hoặc 64bit ELMAH với trang web tùy thuộc vào máy chủ
- 27. Chuyển đổi 32 bit dll sang 64 bit dll
- 28. Visual Studio 2010: Cách đặt nền tảng xây dựng thành Hoạt động (x86)?
- 29. Không thể tải tệp hoặc lắp ráp '***. Dll' hoặc một trong các phụ thuộc của nó
- 30. C++ Trình tải ảnh nền tảng chéo cho OpenGL
Có phải các cụm được quản lý hoặc mã gốc không? –
Tại sao bạn không muốn chỉ xây dựng các phiên bản x86 và x64 của ứng dụng? – outcoldman
Tôi muốn nói rằng chúng được trộn lẫn. De-biên dịch họ đã cho tôi rất nhiều mã được viết bằng C nhưng tôi vẫn không chắc chắn. – Ammark