Cambia C # DllImporta il codice target in base a x64 / x86

Possibile duplicato:
direttiva preprocessore … C #

Ho un dll esterno c ++ da importare usando DLLImport. Se la mia applicazione si sta compilando in x64 ho bisogno di importare la versione x64 di questa dll, se è una build x86, ho bisogno della dll x86.

Qual è il modo migliore per raggiungere questo objective?

Idealmente, mi piacerebbe qualche direttiva per il preprocessore, ma capisco che non funzioni in c #?

Ulteriori informazioni: la DLL viene importata da un progetto impostato su AnyCPU. Un progetto padre è quello che determina se l’applicazione viene compilata come x64 o x86. Compiliamo entrambe le versioni per diversi clienti e voglio condividere il progetto figlio in entrambe le versioni.

Questo è principalmente un problema di distribuzione, basta che l’installatore copi la DLL corretta in base alla versione di Windows sul computer di destinazione.

Ma a nessuno piace mai farlo. La possibilità di imporre dynamicmente la funzione DLL corretta è estremamente dolorosa, è necessario scrivere tipi delegati per ogni funzione esportata e utilizzare LoadLibrary + GetProcAddress + Marshal.GetDelegateForFunctionPointer per creare l’object delegato.

Ma a nessuno piace mai farlo. L’approccio meno doloroso consiste nel dichiarare la funzione due volte, assegnandole nomi diversi e utilizzando la proprietà EntryPoint nell’attributo [DllImport] per specificare il nome reale. Quindi prova in runtime che vuoi chiamare.

Ma a nessuno piace mai farlo. Il trucco più efficace è guidare Windows per caricare la DLL corretta per te. La prima cosa che devi fare è copiare la DLL in una directory dove Windows non la cercherà. Il modo migliore consiste nel creare una sottodirectory “x86” e una “x64” nella directory di build e copiare in ciascuna la DLL appropriata. Fatelo scrivendo un evento post-build che crea le directory e copia le DLL.

Quindi riferiscilo a Windows avviando SetDllDirectory (). Il percorso specificato verrà aggiunto alle directory in cui Windows cerca una DLL. Come questo:

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

Considerare se avere il codice eseguito in modalità a 64 bit è effettivamente utile. È piuttosto raro che sia necessario il gigantesco spazio di indirizzi di memoria virtuale che si ottiene da esso, l’unico vero vantaggio. Devi ancora supportare la versione a 32 bit che deve funzionare correttamente nel caso da 2 gigabyte.

Aggiungi entrambe le importazioni DLL x86 e x86_64 con nomi diversi, quindi puoi invocare condizionalmente a seconda dell’architettura in fase di esecuzione controllando il valore di Environment.Is64BitProcess (o IntPtr.size se stai utilizzando < .Net 4). Questo funzionerà indipendentemente dal fatto che il progetto sia costruito come x86, x86_64 o AnyCPU

In alternativa, configura 2 diverse configurazioni di build, una che fa solo x86 e una che fa solo x86_64, assegna a ciascuna un simbolo di compilazione condizionale e usa un #ifdef sul simbolo personalizzato.