2010-06-03 7 views
16

Ich bin Windows-Entwickler, ich verwende Microsoft Visual Studio 2008 SP1. Meine Entwicklermaschine ist 64 Bit.AnyCPU/x86/x64 für C# -Anwendung und es ist C++/CLI-Abhängigkeit

Die Software, die ich gerade bearbeite, wird verwaltet .exe in C# geschrieben. Leider konnte ich das ganze Problem nicht nur in C# lösen. Deshalb habe ich auch eine kleine gemanagte DLL in C++/CLI entwickelt. Beide Projekte sind in der gleichen Lösung.

Mein C# .exe-Buildziel ist "Any CPU". Wenn mein C++ - DLL-Buildziel "x86" ist, wird die DLL nicht geladen. Soweit ich verstanden habe, wenn ich googled, der Grund ist C++/CLI-Sprache, im Gegensatz zu anderen .NET-Sprachen, kompiliert, um den systemeigenen Code, nicht verwalteten Code.

Ich wechselte das Build-C++ - DLL-Ziel auf x64, und alles funktioniert jetzt. AFAIK funktioniert jedoch nicht mehr, sobald mein Client mein Produkt auf einem 32-Bit-Betriebssystem installiert. Ich muss Windows Vista und 7 unterstützen, 32-und 64-Bit-Versionen von jedem von ihnen.

Ich möchte nicht auf 32 Bits zurückfallen. Diese 250 Zeilen C++ Code in meiner DLL sind nur 2% meiner Codebasis. Und diese DLL wird nur an mehreren Stellen verwendet, daher ist sie im typischen Anwendungsszenario nicht einmal geladen.

Meine DLL implementiert zwei COM-Objekte mit ATL, daher kann ich die Projekteinstellung "/clr:safe" nicht verwenden.

Gibt es Möglichkeit, die Lösung und die Projekte so zu konfigurieren, dass C# Projekt baut „Any CPU“ -Version, die C++ Projekt beiden 32-Bit und 64-Bit-Versionen, dann in der Laufzeit, wenn das verwaltete .EXE beginnt baut up, es verwendet je nach Betriebssystem entweder 32-Bit-DLL oder 64-Bit-DLL?

Oder gibt es vielleicht eine bessere Lösung, die mir nicht bekannt ist?

Vielen Dank im Voraus!

+3

Gibt es ein Grund, warum Sie nicht einfach zwei Versionen verteilen können, eine für x86 und eine für x64? –

+0

Sind Sie sicher, dass Sie das C++ zu CLI kompilieren? – tgiphil

Antwort

7

Es gibt keine einfache Möglichkeit. Wenn Sie nativen Code haben (d. H. Ihr C++) und Sie x86 unterstützen müssen, dann müssen Sie x86 kompilieren (es sei denn, Sie möchten in WOW World arbeiten ... dh 32-Bit-Code in 32- und 64-Bit-Environments ausführen). Sie können haben sowohl eine x86 und x64-Distributionen, aber wenn Sie beide 32 und 64 Bit unterstützen, und Sie haben nativen Code oder COM-Intro 'dann haben Sie haben 32 und 64-Bit-Binärdateien. "Jede CPU" ist nur dann wirklich nützlich, wenn es keinen nativen Code oder Interop gibt, dann bekommt man diesen Vorteil.

+0

Ja, und 98% meines Codes ist in C# geschrieben und verwaltet. Ich möchte wirklich nur 1 Installationspaket beibehalten und die einzige Version meiner Software unterstützen. Ich denke, ich werde mit "Any CPU" weitermachen und wird untersuchen, wie man eine der 2 DLLs dynamisch, in C# code. Danke trotzdem! – Soonts

+0

@Soons Wenn Sie Ihr Installationspaket korrekt erstellen, können Sie die richtigen Binärdateien auswählen und installieren. Das ist, was ich mache, wenn Server-Apps und Idiot-Admins kollidieren :) – Gusdor

10

Es gibt einen Weg: einen "AnyCPU" -C# -Wrapper und ein C++ - Projekt pro Architektur zu haben und den C# -Wrapper das richtige C++ - Projekt zur Laufzeit laden zu lassen.

Erstellen Sie für das C++ - Projekt eine Version für verschiedene Architekturen (x86, x64), und erstellen Sie sie alle. Dann in der Verpackung tun:

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... */ 
    } 
} 

Und im C++ Code verwende ich die gleichen Quellen wie gesagt, aber zu anderen Namespace je nach build Architektur kompilieren:

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

Ihre C# -Klasse kann nicht erstellen, da die C++ verwaltete DLL nur Cpp64 oder Cpp32 enthält, aber nicht beides. – imekon

Verwandte Themen