2017-08-22 3 views
2

die Suche nach Hilfe von Erfahrung Menschen weitergeben, die mit C behandelt haben ++ und C#Wie C++ Objekt zu C#

ich jetzt einen C# -Projekt zu schreiben, die eine vorhandene C++ Funktion in der internen Bibliothek erfordert Aufruf, und einige Schwierigkeiten stoßen .

C++ Code Funktion Kopf

typedef int (*PTR_func) 
(const char*    param1,  // input 
const char*    param2,  // input 
VirtualInternalString& po_output); // Third param is actually the output 

C++ Code-Klasse (änderbar nicht)

namespace InternalLib 
{ 

    class VirtualInternalString 
    { 
     public : 
      virtual ~VirtualInternalString(){}; 
      virtual void _cdecl SetString(const char *) =0; 
      virtual const char * _cdecl c_str() const =0; 
    }; 

    class SafeInternalString :public VirtualInternalString 
    { 
     public : 
      SafeInternalString():TheString(""){}; 
      virtual ~SafeInternalString(){}; 
      virtual void _cdecl SetString(const char * chararray) { TheString = chararray;}; 
      virtual const char * _cdecl c_str() const { return TheString.c_str() ;} ;   // This is the std::string 

     protected: 
      std::string TheString; 
    }; 

    class SafePtrString :public VirtualInternalString 
    { 
     public : 
      SafePtrString():PtrString(0){}; 
      SafePtrString(std::string &str):PtrString(&str){}; 
      virtual ~SafePtrString(){}; 
      virtual void _cdecl SetString(const char * chararray) { (* PtrString) = chararray;}; 
      virtual const char * _cdecl c_str() const { return PtrString->c_str() ;} ; 

     protected : 
      std::string * PtrString; 
    }; 
} 

Nun ist diese zu nutzen, ich habe für das interne String-Objekt (kann nicht geändert werden) "func" in meinem C# -Code. Ich kann die C++ - Funktion richtig aufrufen und verwenden, aber während der Rückgabe der Ausgabe (der dritte Parameter) tritt ein Problem auf. Es sollte ein problembezogener Rückgabetyp sein.

C# (kann geändert werden)

[DllImport("xxxxlib", CallingConvention = CallingConvention.Cdecl)] 
private extern static int func(string param1, 
           string param2, 
           [MarshalAs(UnmanagedType.LPStr)] StringBuilder res); // problem here 

Ich weiß, ich habe eine entsprechende Wrapper erstellen, den C++ decopose in C# String-Objekt, aber ich habe keine Erfahrung darüber. Ich habe mehrere Lösungen aus dem Internet versucht, aber nicht funktioniert.

Weiß jemand, wie ich das umsetzen kann? Würde es Ihnen etwas ausmachen, mir einen einfachen C# -Skelett-Code zu zeigen?

+4

Habe ich vor ein paar Minuten nicht genau diese Frage gesehen? Hast du es gepostet und dann gelöscht? Wenn ja, dann bitte nicht. Stattdessen sollten Sie die Frage bearbeiten, die Sie bereits haben. –

+1

Mögliches Duplikat von [Übergabe von Zeichenfolgen von C# nach C++ dll und zurück - minimales Beispiel] (https: // stackoverflow.com/questions/20752001/passing-strings-von-c-sharp-zu-c-dll-and-back-minimal-beispiel) – vasek

+1

Sorry, dass ... Haben Sie eine Idee zu diesem Beitrag? Das Ziel besteht darin, die Zeichenfolge innerhalb des zurückgegebenen C++ - Objekts abzurufen. Es sollte nicht schwierig sein, aber ich habe es wirklich anders versucht und viel gekämpft. Es funktioniert immer noch nicht – passenger

Antwort

1

Dies ist ein Fall, in dem ich denke, die Verwendung von C++/CLI macht Sinn. Sie möchten möglicherweise eine kleine C++/CLI-Brücke zwischen der systemeigenen C++ - DLL und Ihrem C# -Code erstellen.

Der C++/CLI-Layer ist dafür verantwortlich, Ihre benutzerdefinierte C++ - String-Klasse als Ausgabeparameter von der DLL-Funktion zu übernehmen und von dieser benutzerdefinierten Zeichenfolge in ein C#/.NET-Stringobjekt zu konvertieren.

Ihre benutzerdefinierte C++ - String-Klasse scheint std::string zu wickeln; Auf der anderen Seite verwenden C# /. NET-Zeichenfolgen Unicode UTF-16 als ihre Textcodierung. Daher müssen Sie möglicherweise zwischen Unicode UTF-8 (gespeichert in std::string und in Ihrer benutzerdefinierten Zeichenfolgenklasse) und UTF-16 (für C# /) konvertieren. .NET-Zeichenfolgen).

Entsprechend müssen Sie auch C# UTF-16-Zeichenfolgen in UTF-8 in dieser C++/CLI-Überbrückungsschicht konvertieren und diese UTF-8-codierten Zeichenfolgen als Ihre const char* Eingabeparameter an die native DLL-Funktion übergeben.

+0

Würde es Ihnen etwas ausmachen, eine einfache Code-Struktur zu zeigen ? Das wird toll. – passenger

+0

Ja, vielen Dank für euch alle! Ich habe jetzt eine Ahnung und versuche die C++/CLI-Brücke, um die const char * – passenger

+0

@passenger: Für die Unicode-Encoding-Konvertierungen finden Sie [dieser MSDN-Artikel] (https://msdn.microsoft.com/magazine/ mt763237) interessant. Schauen Sie sich auch diese [Marshalling-Bibliothek] (https://docs.microsoft.com/cpp/dotnet/overview-of-marshaling-in-cpp) an. –

3

vaseks possible duplicate funktioniert nicht, wenn Sie nur die C# -Seite ändern. Aber was Sie tun können, ist Wrapper in C++ erstellen, die char * mit zugehörigen length Parameter erstellen.

Sie erstellen einen zusätzlichen C++ Header und Quelle, die enthält:

int func 
(const char*    param1,  // input 
const char*    param2,  // input 
char*     po_output, // Third param is actually the output 
int      length);  // Length of the buffer allocated by caller 

Und dann machen Sie Ihren func Anruf PTR_func.

+1

Der schwierige Teil ist, dass eine C++ Funktion VirtualInternalString & Objekt zurückgibt, und diese Funktion zu verwenden, erfordert nicht einfach # initialtion C. Meinst du, dass ich eine andere C++ - Funktion erstellen kann, die das char * im Objekt der Außenwelt aussetzt? – passenger

+0

Genau, der zusätzliche 'func'-Wrapper, den Sie erstellen, macht das' char * 'für die Außenwelt verfügbar, während er sich mit dem' VirtualInternalString & '-Objekt auf der Innenseite befasst. – CodeMonkey

+1

@passenger Genau! Um genauer zu sein, müssen Sie _copy_ Daten von 'VirtualInternalString &' in den von C# bereitgestellten Puffer kopieren. Vergessen Sie nicht, die Pufferlänge zu prüfen! – vasek