Fragen zur Typwandlung mittels Marshal!
-
hi! Schreib gerade ne Klassenbibl. inkl Wrapper!
Die C++ Methode lautet:
bool Func1(std::string const & param1, std::string & Error){ }
die Methode des Wrappers:
bool Func2(System::String^ const param1, System::String^ Error){...}
Sind die DT der Wrapper Methode richtig? Also anstatt von string const & -> System::String^ !
Wenn nicht dann bitte um Korrektur!
Wenn ich jetzt aus der Func2 über einen Zeiger auf Func1 zugreifen will, was muss ich da konvertieren?
// Func2 ist die WrapperMethode die Func1 aufruft
bool Func2 (System::Str....) { return mpClassA->Func2(???,???); }
Kann ich die System::String Referenzen direkt übergeben an std::string& ? Bzw den Rückgabewert direkt "durchlassen"?
Danke für eure Mühe!
-
//get a pointer to an array of ANSI chars char *CommPortChars = static_cast<char*> (Marshal::StringToHGlobalAnsi(CommPort).ToPointer()); std::string strCommPort = CommPortChars; char *ErrorStringChars = static_cast<char*> (Marshal::StringToHGlobalAnsi(ErrorString).ToPointer()); std::string strErrorString = ErrorStringChars; System::Boolean ret = mpSerial->OpenSerialport(strCommPort, strErrorString); //free the memory used by the array //since the array is not managed, it will not be claimed by the garbage collector Marshal::FreeHGlobal((IntPtr)CommPortChars); Marshal::FreeHGlobal((IntPtr)ErrorStringChars); return ret;
Hab das ganze nun so gelöst! Jedoch funktioniert das mit den Referenzen nicht so wirklich!
Wenn ich im C# Code ein System::String mitgebe und in der entsprechende Methode im C++ Code (+.dll) eien Wert reinschreibe, steht der nachher nicht in C# zur Verfügung.... ergo haut da was mit der Referenz nicht hin!
Danke für jeden Tipp !
-
Hab das ganze nun so gelöst! Jedoch funktioniert das mit den Referenzen nicht so wirklich!
Wenn ich im C# Code ein System::String mitgebe und in der entsprechende Methode im C++ Code (+.dll) eien Wert reinschreibe, steht der nachher nicht in C# zur Verfügung.... ergo haut da was mit der Referenz nicht hin!
Du wandelst ja nur den System::String zu std::string und nicht zurück. Hier werden Daten kopiert. Gehe nicht davon aus dass Du aus einem System::String einen std::string bekommst dessen Änderung sich auf den System::String auswirkt.
-
LordJaxom schrieb:
Wenn ich im C# Code ein System::String mitgebe und in der entsprechende Methode im C++ Code (+.dll) eien Wert reinschreibe, steht der nachher nicht in C# zur Verfügung.... ergo haut da was mit der Referenz nicht hin!
Du wandelst ja nur den System::String zu std::string und nicht zurück. Hier werden Daten kopiert. Gehe nicht davon aus dass Du aus einem System::String einen std::string bekommst dessen Änderung sich auf den System::String auswirkt.
Stimmt!
Danke!
Aber irgendwie bring ich das nicht zusammen!
System::Boolean HexaComm::OpenSerialport(System::String^ CommPort, System::String^ ErrorString){ // convert System::String to std::string //get a pointer to an array of ANSI chars char *CommPortChars = static_cast<char*> (Marshal::StringToHGlobalAnsi(CommPort).ToPointer()); std::string strCommPort = CommPortChars; char *ErrorStringChars = static_cast<char*> (Marshal::StringToHGlobalAnsi(ErrorString).ToPointer()); std::string strErrorString = ErrorStringChars; System::Boolean ret = mpSerial->OpenSerialport(strCommPort, strErrorString); // convert std::string to System::String ErrorString = Marshal::PtrToStringAnsi((IntPtr)strErrorString.c_str()); //free the memory used by the array //since the array is not managed, it will not be claimed by the garbage collector Marshal::FreeHGlobal((IntPtr)CommPortChars); Marshal::FreeHGlobal((IntPtr)ErrorStringChars); return ret; }
Das ist mein Code! Wieso funktioniert diese Zeile nicht?:
ErrorString = Marshal::PtrToStringAnsi((IntPtr)strErrorString.c_str());
-
Ups hab vergessen die Compilermeldung hinzuzugeben:
error C2440: 'type cast' : cannot convert from 'const char *' to 'System::IntPtr' 1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
-
Leider kann ich die Frage nicht direkt beantworten (wir haben hier auch ein C++/CLI-Forum), aber in dem Code steckt noch ein anderes Problem, dessen Lösung dieses Problem hier gleich mit erschlägt:
Deine Managed-Funktion nimmt (Managed-)Referenzen auf Strings by-value entgegen. Solange Du den String, auf den die (Managed-)Referenz zeigt, direkt ändertst, ist alles ok. Sobald Du einen String zuweist, weist Du ihn der Kopie der (Managed-)Referenz zu, die in der Funktion existiert. Will heissen, die Referenz auf den übergebenen String verfällt in der Funktion, aber von aussen steht in dem was Du als ErrorString übergeben hast, immernoch dasselbe drin.
Die Lösung ist ähnlich wie bei normalem C++: Du musst die System::String-Referenz by-ref übergeben. Da Du ohnehin einen neuen String zuweisen musst, und es einen System::String-Konstruktor für const char* gibt, löst sich damit auch Dein aktuelles Problem (die wichtigen Änderungen in Zeilen 1 und 14):
System::Boolean HexaComm::OpenSerialport(System::String^ CommPort, System::String^% ErrorString){ // <<--- ErrorString als managed by-ref // convert System::String to std::string //get a pointer to an array of ANSI chars char *CommPortChars = static_cast<char*> (Marshal::StringToHGlobalAnsi(CommPort).ToPointer()); std::string strCommPort = CommPortChars; char *ErrorStringChars = static_cast<char*> (Marshal::StringToHGlobalAnsi(ErrorString).ToPointer()); std::string strErrorString = ErrorStringChars; System::Boolean ret = mpSerial->OpenSerialport(strCommPort, strErrorString); // convert std::string to System::String ErrorString = gcnew System::String( strErrorString.c_str() ); // <<--- //free the memory used by the array //since the array is not managed, it will not be claimed by the garbage collector Marshal::FreeHGlobal((IntPtr)CommPortChars); Marshal::FreeHGlobal((IntPtr)ErrorStringChars); return ret; }
Ich denke so müsste es funktionieren, ich beschäftige mich auch erst sehr kurz mit dem Übergang zwischen C++ und C++/CLI
Frag das nächste Mal am besten direkt im C++/CLI-Forum nach sowas, ich denke die Leute dort wissen auch eher solche Sachen wie Umwandlung char* -> IntPtr. Mit Sicherheit werden Sie die Begriffe besser drauf haben.