Wie einen String mit unbekannter größe in ein char konvertieren?
-
Hallo,
ich habe folgendes Problem,
eine funktion die ich aufrufe will auschlieslich einen konstanten char*
nur sol dieser char erst noch aus mehren char zusammen gehängt werden, aber wie hängt man char's zusammen ohne die größe der char's zu kennen?
Also habe ich mich für String entschieden da sich mit dennen ganz einfach Strings's zusammen hängen lassen (StrA = Str1 + Str2 + "text";). Dann müsste ich jetzt nur den fertigen String in Char* konvertieren aber wie wenn ich nicht weis welche größe der fertige String haben wird?
-
Deine String-Klasse (std::string oder irgenein CLI-Gedöns?) gibt dir doch die Größe an. Und bei einem char* kannst du die Größe z.B. über strlen erfahren (Voraussetzung ist eine Nullterminierung).
-
String^ (Visual Studio C++ 2008)
also selbst wenn ich die wagemutige methode nehme und einen char mit einer festen größe wie 255 deklariere, weis ich immer noch nicht wie ich einen String^ in ein Char* konvertiere. Es ist zwar die rede von atoi() und strcpy(),... haut aber alles nicht hihn, weil diese (zumindestens bei mir) zeichensätzen-operanden-funktionen einen char als input voraussetzen.
-
std::string hat eine Methode c_str, CString (MFC) hat GetBuffer, also wird String^ auch irgendwas in der Richtung haben (irgendeine Methode also, die dir einen const char* oder so zurückgibt).
EDIT: ToCharArray vielleicht?
-
_matze schrieb:
std::string hat eine Methode c_str, CString (MFC) hat GetBuffer, also wird String^ auch irgendwas in der Richtung haben (irgendeine Methode also, die dir einen const char* oder so zurückgibt).
EDIT: ToCharArray vielleicht?
Ich bekomme ToCharArray nicht angewendet!
also char* anfrage = anfrageString->ToCharArray funktioniert nicht!
nur array<Char> ^anfrage = anfrageString->ToCharArray;
aber wie der name schon verät Char nicht char!
das scheint was anderes zu sein!
-
System::Char
entsprichtwchar_t
, nichtchar
. Einen Array von Chars könntest du übervolatile pin_ptr<wchar_t>
ansprechen. Ansonsten bleibt nur noch der Weg über Marshaling#include <iostream> using namespace std; using namespace System; using namespace System::Runtime::InteropServices; int main() { String ^foo = L"abcdefghijk"; IntPtr cptr = Marshal::StringToHGlobalAnsi(foo); const char *pfoo = static_cast<const char *>(cptr.ToPointer()); cout << pfoo << endl; Marshal::FreeHGlobal(cptr); // Nicht vergessen zu freen... return 0; }
MfG
-
/rant/ schrieb:
System::Char
entsprichtwchar_t
, nichtchar
. Einen Array von Chars könntest du übervolatile pin_ptr<wchar_t>
ansprechen. Ansonsten bleibt nur noch der Weg über Marshaling#include <iostream> using namespace std; using namespace System; using namespace System::Runtime::InteropServices; int main() { String ^foo = L"abcdefghijk"; IntPtr cptr = Marshal::StringToHGlobalAnsi(foo); const char *pfoo = static_cast<const char *>(cptr.ToPointer()); cout << pfoo << endl; Marshal::FreeHGlobal(cptr); // Nicht vergessen zu freen... return 0; }
MfG
const char* String_to_char(String^ _String) { IntPtr cptr = Marshal::StringToHGlobalAnsi(_String); const char *_char = static_cast<const char *>(cptr.ToPointer()); //cout << pfoo << endl; Marshal::FreeHGlobal(cptr); return _char; }
1>El Em Ci.obj : error LNK2020: Nicht aufgelöstes Token (06000008) AutoMySQL::String_to_char. 1>AutoMySQL.obj : error LNK2020: Nicht aufgelöstes Token (06000003) AutoMySQL::String_to_char.
-
const char* String_to_char(String^ _String) { IntPtr cptr = Marshal::StringToHGlobalAnsi(_String); const char *_char = static_cast<const char *>(cptr.ToPointer()); cout << _char << endl; Marshal::FreeHGlobal(cptr); return _char; }
1>.\AutoMySQL.cpp(55) : error C2065: 'cout': nichtdeklarierter Bezeichner 1>.\AutoMySQL.cpp(55) : error C2065: 'endl': nichtdeklarierter Bezeichner
-
Also sorry ist keine CLR!
Sondern eine Win32!ich denke mal daher das std::cout sowieso raus fliegt
aber #include <iostream> habe ich mal trotzdem gemachthabe aber eine Fehlermeldung
1>El Em Ci.obj : error LNK2020: Nicht aufgelöstes Token (06000008) AutoMySQL::String_to_char. 1>AutoMySQL.obj : error LNK2020: Nicht aufgelöstes Token (06000003) AutoMySQL::String_to_char.
-
LiGERWooD schrieb:
const char* String_to_char(String^ _String) { IntPtr cptr = Marshal::StringToHGlobalAnsi(_String); const char *_char = static_cast<const char *>(cptr.ToPointer()); cout << _char << endl; Marshal::FreeHGlobal(cptr); return _char; }
Das darfst du sowieso nicht! Einen Zeiger auf nicht mehr allokierten Speicher zurückgeben ist nicht gut
Was denn nun, sind wir im falschen Forum oder was?^^
MfG
-
Also genau genommen ist mein Projekt bestanteil aus .Net Visual C++ aber mit einer .Net Framework umgebung, also Windows Forms und so, aber nach wie vohr ist es schon so das es eine
int main() { return 0; }
gibt.
ich wollte jetzt natürlich deinen programmablauf in eine Funktion packen damit ich es einfach immer wieder verwenden kann, etwa so:String^ Ergebnis = "12,5"; char* wert = String_to_char(Ergebnis);
Was ja eigentlich weiter kein Promlem sein dürfte da man ja jede anweisung unter einer Funktion in C/C++ schreibt, nur das dann diese Funktion ja extra für deinen demonstrierten Programmablauf ist und halt natürlich das ergebnis zurück geben sol, also eine const char*
Oder weis ich das nicht und man kann gar keine Funtion mit dem datentyp char defenieren? oder wie kann man es machen so das die char mit dem zugewiessenen ergebnis
const char *pfoo = static_cast<const char *>(cptr.ToPointer());
zurück gegeben wird?
-
hat es vieleicht damit was zu tun das ich die Funktion in einer clase definiere und nicht in der main.cpp?
-
Du solltest dich unbedingt entscheiden was du willst. .Net oder nicht .Net. Sonst bekommt man genau das Problem welches du hast, dass man zwischen managed Code und unmanaged Code Typen marshallen muss. Das ist oftmals einfach unnötig, bisher hast du auch noch keinen Grund genannt warum du C++ und .Net Datentypen mischen müsstest.
-
Talla schrieb:
Du solltest dich unbedingt entscheiden was du willst. .Net oder nicht .Net. Sonst bekommt man genau das Problem welches du hast, dass man zwischen managed Code und unmanaged Code Typen marshallen muss. Das ist oftmals einfach unnötig, bisher hast du auch noch keinen Grund genannt warum du C++ und .Net Datentypen mischen müsstest.
ähm diese Marschallmethode hat mir /rant/ gennant, dann wusste er bis dato nicht das ich .Net verwende, ansonsten decke ich mal das du mein eigentliches Problem verstanden hast das ich einen String in char bekommen muss, weil die funktion die es so braucht stammt von einer libary ab, also dahinter steckt assembler, und diese funktion ist in C aber ich brauche diese funktion für einen vorgang im hintergund zu einer .Net Framework anwendung.
-
LiGERWooD schrieb:
Talla schrieb:
Du solltest dich unbedingt entscheiden was du willst. .Net oder nicht .Net. Sonst bekommt man genau das Problem welches du hast, dass man zwischen managed Code und unmanaged Code Typen marshallen muss. Das ist oftmals einfach unnötig, bisher hast du auch noch keinen Grund genannt warum du C++ und .Net Datentypen mischen müsstest.
ähm diese Marschallmethode hat mir /rant/ gennant, dann wusste er bis dato nicht das ich .Net verwende, ansonsten decke ich mal das du mein eigentliches Problem verstanden hast das ich einen String in char bekommen muss, weil die funktion die es so braucht stammt von einer libary ab, also dahinter steckt assembler, und diese funktion ist in C aber ich brauche diese funktion für einen vorgang im hintergund zu einer .Net Framework anwendung.
Nun, nicht ganz. Ich habe dir diese Marshaler gebracht, weil ich davon ausgegangen bin, dass du beides (also .NET und nativen Code) verwendest. Ansonsten würden Marshaler in dieser Form ja keinen Sinn ergeben. Du kannst diesen Marshaler benutzen, aber du musst den marshaled Speicher kopieren, nicht einfach einen Zeiger auf unallokierten Speicher umerreichen
MfG
-
/rant/ schrieb:
LiGERWooD schrieb:
Talla schrieb:
Du solltest dich unbedingt entscheiden was du willst. .Net oder nicht .Net. Sonst bekommt man genau das Problem welches du hast, dass man zwischen managed Code und unmanaged Code Typen marshallen muss. Das ist oftmals einfach unnötig, bisher hast du auch noch keinen Grund genannt warum du C++ und .Net Datentypen mischen müsstest.
ähm diese Marschallmethode hat mir /rant/ gennant, dann wusste er bis dato nicht das ich .Net verwende, ansonsten decke ich mal das du mein eigentliches Problem verstanden hast das ich einen String in char bekommen muss, weil die funktion die es so braucht stammt von einer libary ab, also dahinter steckt assembler, und diese funktion ist in C aber ich brauche diese funktion für einen vorgang im hintergund zu einer .Net Framework anwendung.
Nun, nicht ganz. Ich habe dir diese Marshaler gebracht, weil ich davon ausgegangen bin, dass du beides (also .NET und nativen Code) verwendest. Ansonsten würden Marshaler in dieser Form ja keinen Sinn ergeben. Du kannst diesen Marshaler benutzen, aber du musst den marshaled Speicher kopieren, nicht einfach einen Zeiger auf unallokierten Speicher umerreichen
MfG
sry, nur hab ich überhaupt keine ahnung von Marshal.
Ist das eine .h oder ein objekt? Und wo finde ich diesen Marshaler überhaupt? Du meinst eine ableitung von Marshaler erstellen, also mit gcnew und so?
-
Es gibt diverse Marshaler. Zum einen hast du die standardmässigen, von .NET bereitgestellten Marshaler von
System::Runtime::InteropServices::Marshal
sowie diverse Marshaling Attribute (für implizites Marshaling von Argumenten beiDllImport
etc.). In Visual C++ (bezogen auf die Professional Version; ob die Aussage auch für die Express Editions gilt, weiss ich nicht) gibt es aber auch noch Header wiemsclr/masrshal.h
, welche nur mit C++/CLI genutzt werden können - und die unter Umständen wesentlich komfortabler sein können.LiGERWooD schrieb:
Du meinst eine ableitung von Marshaler erstellen, also mit gcnew und so?
Das kommt darauf an, welchen Typ von Marshaler du benutzen willst. BTW, eine Ableitung erstellen ist nicht dasselbe wie instanzieren (was du mit
gcnew
, sowie mit einer Deklaration mit auto Semantik tust)...MfG
-
/rant/ schrieb:
Es gibt diverse Marshaler. Zum einen hast du die standardmässigen, von .NET bereitgestellten Marshaler von
System::Runtime::InteropServices::Marshal
sowie diverse Marshaling Attribute (für implizites Marshaling von Argumenten beiDllImport
etc.). In Visual C++ (bezogen auf die Professional Version; ob die Aussage auch für die Express Editions gilt, weiss ich nicht) gibt es aber auch noch Header wiemsclr/masrshal.h
, welche nur mit C++/CLI genutzt werden können - und die unter Umständen wesentlich komfortabler sein können.LiGERWooD schrieb:
Du meinst eine ableitung von Marshaler erstellen, also mit gcnew und so?
Das kommt darauf an, welchen Typ von Marshaler du benutzen willst. BTW, eine Ableitung erstellen ist nicht dasselbe wie instanzieren (was du mit
gcnew
, sowie mit einer Deklaration mit auto Semantik tust)...MfG
Ich verwende Microsoft Visual Studio 2008 C++ und der hate mir auch vorgeschlagen
#include <msclr/masrshal.h>
und mir einen Beispiel Code gezeigt, allerdings lies sich auch da wieder nicht ein mal das Beispiel compilieren, statesen schleuste er mich in die msclr/masrshal.h an die konfliktzeile. Allerdings ist wohl klar das das Problem ganz wo anders liegt, nämlich warscheinlich an mir. Ich demonstrierie hier noch mal das Beispiel und den Fehler
// C4996_Marshal.cpp // compile with: /clr // C4996 expected #include <stdlib.h> #include <string.h> #include <msclr\marshal.h> using namespace System; using namespace msclr::interop; int main() { String^ message = gcnew String("Test String to Marshal"); const char* result; result = marshal_as<const char*>( message ); return 0; }
Hier meine anpassung
const char* String_to_char(String^ _String) { String^ message = gcnew String("Test String to Marshal"); const char* result; result = marshal_as<const char*>( message ); return result; }
1>C:\Programme\Microsoft Visual Studio 9.0\VC\include\msclr\marshal.h(203) : error C4996: 'msclr::interop::error_reporting_helper<_To_Type,_From_Type>::marshal_as': This conversion requires a marshal_context. Please use a marshal_context for this conversion. 1> with 1> [ 1> _To_Type=const char *, 1> _From_Type=System::String ^ 1> ] 1> C:\Programme\Microsoft Visual Studio 9.0\VC\include\msclr\marshal.h(194): Siehe Deklaration von 'msclr::interop::error_reporting_helper<_To_Type,_From_Type>::marshal_as' 1> with 1> [ 1> _To_Type=const char *, 1> _From_Type=System::String ^ 1> ] 1> .\AutoMySQL.cpp(62): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "_To_Type msclr::interop::marshal_as<const char*,System::String^>(const _From_Type &)". 1> with 1> [ 1> _To_Type=const char *, 1> _From_Type=System::String ^ 1> ]
-
Nun, die Fehlermeldung ist meiner Meinung nach recht eindeutig. Nach
const char *
zu marshalen lässt eben die Frage offen, wem der Speicher dann gehört. Und dafür brauchst du denmarshal_context
. Dieser Kontext übernimmt für dich die Verwaltung der marshaled Objekte; wenn der Kontext in seinem Scope ungültig wird, wird der marshaled Speicher frei gegeben. So funktioniert es.MfG
-
Mir reieieieieieichtssss!
Ich habe keine lust mehr!
Ich habe das gefühl das al diese sachen für eine CLR anwendung sind und in einer Win32 Anwendung sich nicht mit compilieren lassen.Denn warum zut teufel funktionieren nicht mal die Beispiele obwohl ich sie in Original zu stand gelassen habe?!
Warum macht man es hier einem so schwer wen man doch genauso einfach String^ in Integer wandeln kann und es dafür schon Bibliotheken mit den Funktionen gibt?
ich geh nach hause