2009-12-01 3 views
11

Ich bin ein bisschen rostig, eigentlich sehr rostig mit meinem C++. Ich habe es seit Freshman Collegejahr nicht mehr berührt, also ist es schon eine Weile her.Managed C++, um eine Brücke zwischen C# und C++ zu bilden

Wie auch immer, ich mache das Gegenteil von dem, was die meisten Leute machen. Aufruf von C# -Code aus C++. Ich habe etwas online recherchiert und es scheint, als müsste ich etwas gemanagtes C++ erstellen, um eine Brücke zu bilden. Verwenden Sie __declspec (dllexport) und erstellen Sie dann eine DLL und verwenden Sie das Ganze als Wrapper.

Aber mein Problem ist - ich habe wirklich eine harte Zeit, Beispiele zu finden. Ich fand einige grundlegende Sachen, wo jemand die C# Version zu String.ToUpper() verwenden wollte, aber das war sehr einfach und war nur ein kleines Code-Snippet.

Wer hat irgendwelche Ideen, wo ich etwas konkreter suchen kann? Beachten Sie, dass ich COM nicht verwenden möchte. Das Ziel ist, den C# -Code überhaupt nicht zu berühren.

+0

Wie kompliziert ist die Schnittstelle, die Sie unmanaged C/C++ aussetzen möchten? – CuppM

+0

Siehe diesen Link für eine ähnliche Frage/Antwort: http://stackoverflow.com/questions/13293888/how-to-call-ac-sharp-library-from-native-c-using-c-cli-and-ijw . – amalgamate

Antwort

11

Während Lain mich schlagen ein Beispiel zu schreiben, ich es ohnehin nur für den Fall schreiben werde ...

Der Prozess einen Wrapper schreiben Sie Ihre eigene Bibliothek zugreifen entspricht dem Zugriff auf eine der Standardbibliotheken von .Net.

Beispiel C# Klasse Code in einem Projekt namens CsharpProject:

using System; 

namespace CsharpProject { 
    public class CsharpClass { 
     public string Name { get; set; } 
     public int Value { get; set; } 

     public string GetDisplayString() { 
      return string.Format("{0}: {1}", this.Name, this.Value); 
     } 
    } 
} 

Sie würden eine verwaltete C++ Klassenbibliothek Projekt erstellen (Beispiel CsharpWrapper) und C# Projekt als es Verweis hinzuzufügen. Um dieselbe Header-Datei für die interne Verwendung und im referenzierenden Projekt zu verwenden, müssen Sie die richtige Deklaration verwenden. Dies kann durch Definieren einer Präprozessordirektive (CSHARPWRAPPER_EXPORTS in diesem Fall) und Verwenden einer #ifdef, um das Exportmakro in Ihrer C/C++ - Schnittstelle in einer Headerdatei zu setzen. Die nicht verwaltete Schnittstellen-Header-Datei muss nicht verwaltetes Material enthalten (oder vom Präprozessor herausgefiltert werden).

Nicht verwaltete C++ Interface Header Datei (CppInterface.h):

Dann können Sie eine interne Header-Datei erstellen, um in Ihre verwalteten Bibliotheksdateien aufnehmen zu können. Dies fügt die using namespace Anweisungen hinzu und kann Hilfsfunktionen enthalten, die Sie benötigen.

Managed C++ Schnittstelle Header-Datei (CsharpInterface.h):

#pragma once 

#include <string> 

// .Net System Namespaces 
using namespace System; 
using namespace System::Runtime::InteropServices; 

// C# Projects 
using namespace CsharpProject; 


////////////////////////////////////////////////// 
// String Conversion Functions 

inline 
String^ToManagedString(const char * pString) { 
return Marshal::PtrToStringAnsi(IntPtr((char *) pString)); 
} 

inline 
const std::string ToStdString(String^strString) { 
IntPtr ptrString = IntPtr::Zero; 
std::string strStdString; 
try { 
    ptrString = Marshal::StringToHGlobalAnsi(strString); 
    strStdString = (char *) ptrString.ToPointer(); 
} 
finally { 
    if (ptrString != IntPtr::Zero) { 
    Marshal::FreeHGlobal(ptrString); 
    } 
} 
return strStdString; 
} 

Dann schreiben Sie einfach Ihre Interface-Code, der die Verpackung der Fall ist.

Managed C++ Schnittstelle Quelldatei (CppInterface.cpp):

#include "CppInterface.h" 
#include "CsharpInterface.h" 

std::string GetDisplayString(const char * pName, int iValue) { 
CsharpClass^oCsharpObject = gcnew CsharpClass(); 

oCsharpObject->Name = ToManagedString(pName); 
oCsharpObject->Value = iValue; 

return ToStdString(oCsharpObject->GetDisplayString()); 
} 

Dann sind nur die nicht verwaltete Header in Ihrem nicht verwalteten Projekt, den Linker sagen die generierte LIB-Datei zu verwenden, wenn die Verknüpfung, und stellen Sie sicher, dass die .NET- und Wrapper-DLLs befinden sich im selben Ordner wie Ihre nicht verwaltete Anwendung.

#include <stdlib.h> 

// Include the wrapper header 
#include "CppInterface.h" 

void main() { 
// Call the unmanaged wrapper function 
std::string strDisplayString = GetDisplayString("Test", 123); 

// Do something with it 
printf("%s\n", strDisplayString.c_str()); 
} 
+0

Sie erklärten die Dinge ein bisschen mehr - ich wünschte, ich hätte beide Antworten auswählen können. Vielen Dank! –

+0

Strings sind ein gutes Beispiel, da die Konvertierungsfunktionen erforderlich sind, sobald Sie eine Zeichenfolge von nativ zu verwaltet marshallen müssen (was normalerweise in den meisten Interop-Umgebungen ziemlich bald der Fall ist!) – Iain

+0

Für die "Keine solche Datei oder Verzeichnis" müssen Sie entweder: 1) Füge 'CppInterface.h' zur nicht verwalteten App hinzu. Ich würde das nicht tun, wenn alle Projekte am selben Ort/Repository leben. Da Sie dann doppelte Dateien verwalten müssen. 2) Fügen Sie den Pfad zu den Wrapper-Projektdateien unter dem Compile Include-Ordner der nicht verwalteten Anwendung hinzu. Für Visual Studio, klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie "Eigenschaften". Dann fügen Sie unter "Konfigurationseigenschaften" -> "C/C++" -> "Allgemein" -> "Zusätzliche Include-Verzeichnisse" den Pfad zum Speicherort von "CppInterface.h" hinzu. – CuppM

10

Erstellen Sie ein neues C++/CLI-Projekt in Visual Studio und fügen Sie einen Verweis zu Ihrer C# -Dll hinzu. Angenommen, wir eine C# DLL namens DotNetLib.dll mit dieser Klasse haben in:

namespace DotNetLib 
{ 
    public class Calc 
    { 
     public int Add(int a, int b) 
     { 
      return a + b; 
     } 
    } 
} 

nun eine CLR C++ Klasse zu Ihrem C hinzufügen ++/CLI-Projekt:

// TestCPlusPlus.h 

#pragma once 

using namespace System; 
using namespace DotNetLib; 

namespace TestCPlusPlus { 

    public ref class ManagedCPlusPlus 
    { 
    public: 
     int Add(int a, int b) 
     { 
      Calc^ c = gcnew Calc(); 
      int result = c->Add(a, b); 
      return result; 
     } 
    }; 
} 

Dies ruft C# von C++.

Jetzt benötigt, wenn Sie eine native C++ Klasse zu Ihrem C++/CLI-Projekt hinzufügen können, die auf die CLR C++ Klasse sprechen können:

// Native.h 
#pragma once 

class Native 
{ 
public: 
    Native(void); 
    int Add(int a, int b); 
    ~Native(void); 
}; 

und:

// Native.cpp 
#include "StdAfx.h" 
#include "Native.h" 
#include "TestCPlusPlus.h" 

Native::Native(void) 
{ 
} 

Native::~Native(void) 
{ 
} 

int Native::Add(int a, int b) 
{ 
    TestCPlusPlus::ManagedCPlusPlus^ c = gcnew TestCPlusPlus::ManagedCPlusPlus(); 
    return c->Add(a, b); 
} 

Sie sollten in der Lage sein, Rufen Sie die Native-Klasse wie üblich von anderen nativen C++ - DLLs auf.

Beachten Sie auch, dass sich Managed C++ von C++/CLI unterscheidet und von ihm übertroffen wurde. Wikipedia erklärt es am besten:

Verwandte Themen