簡體   English   中英

根據 x64/x86 更改 C# DllImport 目標代碼

[英]Change C# DllImport target code depending on x64/x86

我有一個使用 DLLImport 導入的外部 c++ dll。 如果我的應用程序在 x64 中編譯,我需要導入這個 dll 的 x64 版本,如果它是 x86 版本,我需要 x86 dll。

實現這一目標的最佳方法是什么?

理想情況下,我想要一些預處理器指令,但我知道這在 c# 中不起作用?

更多信息:DLL 正在由設置為 AnyCPU 的項目導入。 父項目是決定應用程序編譯為 x64 還是 x86 的項目。 我們為不同的客戶編譯兩個版本 - 我想在兩個版本中共享子項目。

這主要是一個部署問題,只需讓您的安裝程序根據目標計算機上的 Windows 版本復制正確的 DLL。

但從來沒有人喜歡這樣做。 動態調用正確的 DLL 函數非常痛苦,您必須為每個導出的函數編寫委托類型,並使用 LoadLibrary + GetProcAddress + Marshal.GetDelegateForFunctionPointer 創建委托對象。

但從來沒有人喜歡這樣做。 不太痛苦的方法是兩次聲明函數,給它不同的名稱,並使用 [DllImport] 屬性中的 EntryPoint 屬性來指定真實名稱。 然后在運行時測試要調用的。

但從來沒有人喜歡這樣做。 最有效的技巧是引導 Windows 為您加載正確的 DLL。 您必須做的第一件事是將 DLL 復制到 Windows 不會查找的目錄中。 最好的方法是在您的構建目錄中創建一個“x86”和一個“x64”子目錄,並將適當的 DLL 復制到每個子目錄中。 通過編寫創建目錄並復制 DLL 的構建后事件來實現。

然后通過調用 SetDllDirectory() 將它告訴 Windows。 您指定的路徑將添加到 Windows 搜索 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();
        //etc..
    }
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool SetDllDirectory(string path);
}

請考慮在 64 位模式下運行代碼是否對您有用。 很少需要從中獲得巨大的虛擬內存地址空間,這是唯一真正的好處。 您仍然需要支持在 2 GB 的情況下需要正確運行的 32 位版本。

添加具有不同名稱的 x86 和 x86_64 DLL 導入,然后您可以通過檢查 Environment.Is64BitProcess(或 IntPtr.size,如果您使用 <.Net 4)的值,根據運行時的架構有條件地調用它們。 無論項目是構建為 x86、x86_64 還是 AnyCPU,這都將起作用

或者,設置 2 種不同的構建配置 - 一種僅適用於 x86,一種僅適用於 x86_64,為每個配置提供一個條件編譯符號並在您的自定義符號上使用 #ifdef。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM