Alterar o código de destino C # DllImport, dependendo do x64 / x86

Duplicar Possível:
diretiva de pré-processador… C #

Eu tenho uma dll externa c ++ para importar usando DLLImport. Se meu aplicativo está compilando em x64 eu preciso importar a versão x64 desta dll, se for uma compilation x86, eu preciso da dll x86.

Qual a melhor maneira de alcançar isto?

Idealmente, eu gostaria de alguma diretiva de pré-processador, mas eu entendo que isso não funciona em c #?

Mais informações: a DLL está sendo importada por um projeto que está definido como AnyCPU. Um projeto pai é aquele que determina se o aplicativo é compilado como x64 ou x86. Nós compilamos as duas versões para clientes diferentes – e eu quero compartilhar o projeto filho em ambas as versões.

Isso é basicamente um problema de implantação, basta fazer com que o instalador copie a DLL correta com base na versão do Windows na máquina de destino.

Mas ninguém gosta de fazer isso. Dinamicamente pinvoking a function da DLL correta é extremamente dolorosa, você deve escrever tipos de delegado para cada function exportada e usar LoadLibrary + GetProcAddress + Marshal.GetDelegateForFunctionPointer para criar o object de delegado.

Mas ninguém gosta de fazer isso. A tarefa menos dolorosa é declarar a function duas vezes, dando a ela nomes diferentes e usando a propriedade EntryPoint no atributo [DllImport] para especificar o nome real. Em seguida, teste em tempo de execução que você deseja chamar.

Mas ninguém gosta de fazer isso. O truque mais eficaz é orientar o Windows para carregar a DLL correta para você. A primeira coisa que você precisa fazer é copiar a DLL em um diretório em que o Windows não a procurará. A melhor maneira é criar um subdiretório “x86” e um “x64” em seu diretório de compilation e copiar a DLL apropriada em cada um. Faça isso escrevendo um evento de pós-compilation que cria os diretórios e copia as DLLs.

Em seguida, informe o Windows sobre isso definindo SetDllDirectory (). O caminho que você especificar será adicionado aos diretórios que o Windows procura por uma DLL. Como isso:

 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); } 

Considere se ter o código executado no modo de 64 bits é realmente útil para você. É muito raro precisar do espaço de endereço de memory virtual gigante que você obtém dele, o único benefício real. Você ainda precisa suportar a versão de 32 bits que precisa operar corretamente no caso de 2 gigabytes.

Adicione as importações x86 e x86_64 DLL com nomes diferentes e, em seguida, condicionalmente, invoque-as dependendo da arquitetura em tempo de execução, verificando o valor de Environment.Is64BitProcess (ou IntPtr.size se estiver usando <.Net 4). Isso funcionará independentemente de o projeto ser construído como x86, x86_64 ou AnyCPU

Alternativamente, configure 2 configurações de compilation diferentes – uma que faça x86 e outra que faça x86_64, dê a cada uma delas um símbolo de compilation condicional e use um #ifdef em seu símbolo personalizado.