2010-06-03 3 views
16

Sono uno sviluppatore Windows, sto usando Microsoft Visual Studio 2008 SP1. La mia macchina per sviluppatori è a 64 bit.AnyCPU/x86/x64 per l'applicazione C# ed è dipendenza C++/CLI

Il software al momento sto lavorando è gestito .exe scritto in C#. Sfortunatamente, non ero in grado di risolvere l'intero problema esclusivamente in C#. Ecco perché ho sviluppato anche una piccola DLL gestita in C++/CLI. Entrambi i progetti sono nella stessa soluzione.

Il mio obiettivo di build C# .exe è "Qualsiasi CPU". Quando il mio obiettivo di compilazione della DLL C++ è "x86", la DLL non viene caricata. Per quanto ho capito quando ho cercato su google, il motivo è il linguaggio C++/CLI, a differenza di altri linguaggi .NET, compila il codice nativo, non il codice gestito.

Ho cambiato il target di build della DLL C++ in x64 e tutto funziona ora. Tuttavia, AFAIK cesserà di funzionare non appena il mio client installerà il mio prodotto su un sistema operativo a 32 bit. Devo supportare Windows Vista e 7, entrambe le versioni a 32 e 64 bit di ciascuna di esse.

Non voglio tornare a 32 bit. Quelle 250 righe di codice C++ nella mia DLL sono solo il 2% della mia base di codice. E quella DLL viene utilizzata solo in più punti, quindi nello scenario di utilizzo tipico non viene nemmeno caricata.

La mia DLL implementa due oggetti COM con ATL, quindi non posso usare l'impostazione di progetto "/clr:safe".

Non c'è modo per configurare la soluzione ed i progetti in modo che C# progetto si basa la versione "Qualsiasi CPU", il progetto C++ costruisce entrambe le versioni 32 bit e 64 bit, quindi nel runtime quando l'exe gestito sta iniziando up, utilizza DLL a 32 bit o DLL a 64 bit a seconda del sistema operativo?

O forse c'è qualche soluzione migliore di cui non sono a conoscenza?

Grazie in anticipo!

+3

C'è un motivo per cui non puoi semplicemente distribuire due versioni, una per x86 e una per x64? –

+0

Sei sicuro di voler compilare il C++ in CLI? – tgiphil

risposta

7

Non esiste un modo semplice per aggirarlo. Se hai codice nativo (cioè il tuo C++) e devi supportare x86, allora devi compilare x86 (a meno che tu non voglia lavorare nel mondo WOW ... cioè eseguendo codice a 32 bit in envrionment sia a 32 che a 64 bit). È possibile avere entrambe le distribuzioni x86 e x64, ma se si supporta sia 32 e 64 bit, e si dispone di codice nativo o introp COM 'quindi è devono hanno entrambi i binari a 32 e 64 bit. "Any CPU" è utile solo quando non ci sono codici nativi o interop, quindi si ottiene quel vantaggio.

+0

Sì, e il 98% del mio codice è scritto in C# ed è gestito. Mi piacerebbe davvero mantenere solo 1 pacchetto di installazione e supportare l'unica versione del mio software. Penso che andrò avanti con "Any CPU", e indagherò su come caricare una delle 2 DLL in modo dinamico, nel codice C# .. Grazie comunque! – Soonts

+0

@Soonts se si crea correttamente il pacchetto di installazione, è possibile selezionarlo e installare i file binari corretti. Questo è quello che faccio quando le app del server e gli amministratori idiota si scontrano :) – Gusdor

10

C'è un modo: avere un wrapper C# "AnyCPU" e un progetto C++ per architettura, e lasciare che il wrapper C# carichi il giusto progetto C++ in fase di esecuzione.

Per il progetto C++, creare una versione per architettura diversa (x86, x64) e crearli tutti. Poi nella confezione fare:

public class CppWrapper 
{ 
    // C++ calls that will be dynamically loaded from proper architecture: 
    public static readonly Func<long> MyCplusplusMethodUsableFromCsharpSpace; 

    // Initialization: 
    static CppWrapper() 
    { 
     if(Environment.Is64BitProcess) 
     { 
      MyCplusplusMethodUsableFromCsharpSpace = CppReferences64.MyCplusplusClass.Method; 
      // Add your 64-bits entry points here... 
     } 
     else 
     { 
      MyCplusplusMethodUsableFromCsharpSpace = CppReferences32.MyCplusplusClass.Method; 
      /* Initialize new 32-bits references here... */ 
     } 
    } 

    // Following classes trigger dynamic loading of the referenced C++ code 
    private static class CppReferences64 
    { 
     public static readonly Func<long> MyCplusplusMethod = Cpp64.MyCplusplusMethod; 
     /* Add any64-bits references here... */ 
    } 
    private static class CppReferences32 
    { 
     public static readonly Func<long> MyCplusplusMethod = Cpp32.MyCplusplusMethod; 
     /* Add any 32-bits references here... */ 
    } 
} 

E nel codice C++, io uso le stesse fonti, come ho detto, ma sarà la compilazione di diversi namespace a seconda del accumulo architettura:

#ifdef _M_X64 
namespace Cpp64 { 
#else 
namespace Cpp32 { 
#endif 
    public ref class MyCPlusPlusClass 
    { 
     public: static __int64 Method(void) { return 123; } 
    }; 
} 
+0

La tua classe C# non può essere compilata, poiché la DLL gestita da C++ conterrà solo Cpp64 o Cpp32 ma non entrambi. – imekon