WINAPI und LPWCH, LPCH, LPCWSTR, LPCSTR.... ?!



  • Hallo zusammen,

    erst mal kurz zu mir:
    Ich bin ein Neuling auf dem Gebiet C++ und WINAPI Programmierung.
    Hab mich jetzt mit den Grundlagen und der Syntax von C++ weitgehend auseinandergesetzt und würde jetzt gerne mit WINAPI ein paar Sachen machen, bevor ich MFC und Konsorten ausprobiere.

    Irgendwie krieg ichs jedoch nicht auf die Reihe einfachste Sachen zu machen,
    da mir die vielen verschiedenen "Datentypen" für "strings" bzw "chars" ziemliche Schwierigkeiten bereiten.
    Steinigt mich jetzt bitte nicht gleich wegen meiner Unwissenheit, oder weil die Frage sicher schon 1000 mal gestellt wurde.

    Verschiedenste Funktionen der WINAPI verlangen verschiedenste Typen von LPCSTR bis LPCH...
    Erst mal hab ich keinen Plan was eigl was ist. Dann gibts auch noch die meisten Funktionen mit nem 'A' oder 'W' am Ende, die dann die Parameter leicht abändern.

    Ich würde für meine Projekte gern den UNICODE Zeichensatz verwenden, berichtigt mich bitte, wenn ich das nicht tun sollte.

    Jetzt meine Frage nochmal genauer formuliert:
    Sollte ich meine Parameter jetzt je nach verlangtem Typ casten oder gibt es andere, bessere Möglichkeiten ans Ziel zu kommen?
    Und wieso gibts eigl so viel verschiedene Typen?

    😕



  • http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx

    Und für Unicode gibt's Makros soweit ich weiß, das A oder W am Ende muss man dann nicht mit schreiben.



  • Benutze Visual Studio. Dann hoverst du über die Begriffe und siehst die Definitionen. Und dann kannst du auch den Unicode-Zeichensatz einstellen.

    Hinter all diesem Glump verbirgt sich letztens nur char, wchar_t und Pointer darauf.



  • evilplayground schrieb:

    Hallo zusammen,

    erst mal kurz zu mir:
    Ich bin ein Neuling auf dem Gebiet C++ und WINAPI Programmierung.
    Hab mich jetzt mit den Grundlagen und der Syntax von C++ weitgehend auseinandergesetzt und würde jetzt gerne mit WINAPI ein paar Sachen machen, bevor ich MFC und Konsorten ausprobiere.

    Irgendwie krieg ichs jedoch nicht auf die Reihe einfachste Sachen zu machen,
    da mir die vielen verschiedenen "Datentypen" für "strings" bzw "chars" ziemliche Schwierigkeiten bereiten.
    Steinigt mich jetzt bitte nicht gleich wegen meiner Unwissenheit, oder weil die Frage sicher schon 1000 mal gestellt wurde.

    Verschiedenste Funktionen der WINAPI verlangen verschiedenste Typen von LPCSTR bis LPCH...
    Erst mal hab ich keinen Plan was eigl was ist. Dann gibts auch noch die meisten Funktionen mit nem 'A' oder 'W' am Ende, die dann die Parameter leicht abändern.

    Ich würde für meine Projekte gern den UNICODE Zeichensatz verwenden, berichtigt mich bitte, wenn ich das nicht tun sollte.

    Jetzt meine Frage nochmal genauer formuliert:
    Sollte ich meine Parameter jetzt je nach verlangtem Typ casten oder gibt es andere, bessere Möglichkeiten ans Ziel zu kommen?
    Und wieso gibts eigl so viel verschiedene Typen?

    😕

    1. Die Funktionen mit A beschreiben Multibyte-, Funktionen mit W beschreiben Wide-Character-Versionen. Diese Typen sind eigentlich gleich und doch wieder nicht ... beide speichern Buchstaben ab, aber das Format ist nicht dasselbe.

    Multibytes (nativ char ) können 1 oder mehr Bytes belegen, je nach verwendeter Codepage und dem Wert des ersten Bytes. Nützlich, wenn du im japanischen Kanji oder in den chinesischen Silben schreibst.

    Wide-Characters (ab einem gewissen Standard nativ wchar_t ) belegen immer zwei Byte. Codepages sind ihnen fremd, du kannst also in einem Wide-Character-String sowohl Kanji, chinesische Zeichen und das lateinische Alphabet sichern, ohne die Codepage zu wechseln oder mit Führungszeichen zu arbeiten.

    (Ach ja, je nachdem, ob dein OS Unicode und damit Wide-Characters unterstützt, wird automatisch gewählt, welche Funktionsversion eingeblendet wird. GetProcAddress gibt es z.B. nicht, nur GetProcAddressA und GetProcAddressW .)

    2. Die verschiedenen Typen verwirren mich auch. Schau bei Funktionen immer die typedef s nach und bleib ansonsten bei char* und wchar_t* .



  • Danke erst mal für die schnellen Antworten!
    Ich glaub langsam blick ich ein bisschen durch.

    Hab mir mal die Definitionen auf dem msdn-link angeschaut.
    Manchmal denkt man an die einfachsten Sachen nicht...
    Was was ist, dürfte jetzt klar sein 😉

    Ich benutze Visual C++ Express 2008 und Windows XP SP3.
    Unter den Projekteigenschaften ist Unicode als Zeichensatz gewählt.

    @VS_noob:
    Was meinst du mit hovern und dann kann ich den Zeichensatz einstellen?
    Ich seh dann zwar die Definition, kann aber nix einstellen...

    @Glühbirne:
    Fettes Thx für die ausführliche Erklärung, hat mir echt auf die Sprünge geholfen!!!

    Jetzt noch ein paar Fragen zum Verständnis:

    Wenn ich ein Projekt mit Unicode als Zeichensatz verwende, soll ich also am besten meine "strings" als wchar_t[] definieren?
    Oder steh ich jetzt immer noch aufm Schlauch?

    Ein einfaches Beispiel:
    Ich hab mir ne kleine Funktion geschrieben (zum Testen), die mir den executionpath meiner exe zurückgibt. Wäre das jetzt so korrekt?

    //Get the execution Path
    wchar_t* GetExecutionPath()
    {
    	wchar_t Buffer[_MAX_PATH];
    	HINSTANCE hInstance = GetModuleHandle(NULL);
    	GetModuleFileName(hInstance, Buffer, MAX_PATH );
    	return Buffer;
    }
    

    Die Funktion GetModuleFileName() nimmt ja jetzt, da Unicode aktiv, nur einen LPWCH, also einen wchar_t.



  • Wenn du dich darum kümmern mußt, solltest du lieber TCHAR[] verwenden - das wird je nach deinen Projekteinstellungen auf den richtigen Datentyp (char oder wchar_t) übersetzt.

    @Glühbirne: Ich erinnere mich düster, daß die Auswahl nicht vom System abhängt, sondern von den Projekteinstellungen beim Compilieren. Außerdem hast du noch den Ansi-Zeichensatz unterschlagen.



  • Du solltest TCHAR statt wchar_t oder char benutzen 😉
    Das wird abhängig davon ob du Unicode aktiviert hast oder nicht automatisch zu wchar_t (bei UNICODE) bzw. char.

    Damit kann dir dann quasi (bzgl. der meisten WinAPI-Funktionen) völlig egal sein ob Unicode nun aktiv ist oder nicht.

    (Edit: zu langsam ^^)



  • Danke! Danke! Danke!
    TCHAR scheint ja alle Probleme zu erschlagen!

    @CStoll: Was meinst du damit, wenn ich mich darum kümmern muss?
    Wenn ich WINAPI Funktionen benutzen möchte, muss ich mich wohl oder übel darum kümmern, oder?



  • evilplayground schrieb:

    @CStoll: Was meinst du damit, wenn ich mich darum kümmern muss?
    Wenn ich WINAPI Funktionen benutzen möchte, muss ich mich wohl oder übel darum kümmern, oder?

    Ich denke, genau das wollte ich damit ausdrücken. Bei Strings, die du mit der WinAPI austauschen willst, solltest du grundsätzlich mit TCHAR, LPTSTR und Co. arbeiten.
    (was nicht heißt, daß du für interne Verwendung kein char einsetzen darfst - mitunter ist es notwendig, wenn du beim ÜBergang zur WinAPI aufpasst)



  • CStoll schrieb:

    evilplayground schrieb:

    @CStoll: Was meinst du damit, wenn ich mich darum kümmern muss?
    Wenn ich WINAPI Funktionen benutzen möchte, muss ich mich wohl oder übel darum kümmern, oder?

    Ich denke, genau das wollte ich damit ausdrücken. Bei Strings, die du mit der WinAPI austauschen willst, solltest du grundsätzlich mit TCHAR, LPTSTR und Co. arbeiten.
    (was nicht heißt, daß du für interne Verwendung kein char einsetzen darfst - mitunter ist es notwendig, wenn du beim ÜBergang zur WinAPI aufpasst)

    Alles klar, dann nochmal danke für die ausführlichen Erklärungen
    und sry falls ich den ein oder anderen mit Noob-Fragen genervt hab 😉

    Wieder einen Schritt weiter auf dem steinigen C++ Pfad..



  • @Glühbirne:
    GetProcAddress(..) ist ein schlechtes Bsp. in diesem Zusammenhang, da es keine A bzw. W Variante gibt, sondern nur die GetProcAddress(..).



  • theta schrieb:

    @Glühbirne:
    GetProcAddress(..) ist ein schlechtes Bsp. in diesem Zusammenhang, da es keine A bzw. W Variante gibt, sondern nur die GetProcAddress(..).

    Ich meine mich dunkel daran erinnern zu können, in einem meiner Projekte mit GetProcAddress gearbeitet zu haben. Wäre auch kein Wunder, denn der zweite Parameter muss, egal ob Funktionsname oder Ordinalzahl, ein String sein, und davon gibt es nun mal zwei Versionen.

    CStoll schrieb:

    @Glühbirne: Ich erinnere mich düster, daß die Auswahl nicht vom System abhängt, sondern von den Projekteinstellungen beim Compilieren. Außerdem hast du noch den Ansi-Zeichensatz unterschlagen.

    Auch, aber nur, wenn du die Präprozessordirektive UNICODE aktivierst UND das OS auch Unicode unterstützt. Zudem habe ich geschrieben, dass, wenn man explizit eine bestimmte Funktionsversion haben will, entweder A oder W an den Namen anhängen muss.

    Und was den ANSI-Zeichensatz angeht, den meinte ich eigentlich mit Multibyte. Schließlich gibt es so viele Codepages einige verwenden 1, andere mehr Byte pro Zeichen. Ich persönlich treffe auf den Begriff ANSI nur, wenn von 1-Byte-Codierungen die Rede ist - aber noch einmal, sicher bin ich nicht 100%-ig.



  • Glühbirne schrieb:

    Ich meine mich dunkel daran erinnern zu können, in einem meiner Projekte mit GetProcAddress gearbeitet zu haben. Wäre auch kein Wunder, denn der zweite Parameter muss, egal ob Funktionsname oder Ordinalzahl, ein String sein, und davon gibt es nun mal zwei Versionen.

    Falsch. Es gibt ein Version und die nimmt ein LPCSTR.
    Guck in die Header Files, guck in der MSDN Doku, guck in Jeffrey Richters "Advanced Windows" - Advanced Windows | ISBN: 9781572315488

    ➡ Deshalb schlechtes Bsp. in diesem Zusammenhang.



  • theta schrieb:

    ➡ Deshalb schlechtes Bsp. in diesem Zusammenhang.

    Verdammt, ich hätte schwören können ... meine Fresse ... 😮 ... werd' ich etwa alt?



  • Glühbirne schrieb:

    Und was den ANSI-Zeichensatz angeht, den meinte ich eigentlich mit Multibyte. Schließlich gibt es so viele Codepages einige verwenden 1, andere mehr Byte pro Zeichen. Ich persönlich treffe auf den Begriff ANSI nur, wenn von 1-Byte-Codierungen die Rede ist - aber noch einmal, sicher bin ich nicht 100%-ig.

    Es gibt drei verschiedene Zeichensätze - ANSI (1 Byte Zeichen), MULTIBYTE (variable Zeichengröße) und UNICODE (2 Byte). Allerdings werden die ersten beiden Varianten beide durch char's abgebildet und von vielen Funktionen identisch behandelt.



  • CStoll schrieb:

    Es gibt drei verschiedene Zeichensätze - ANSI (1 Byte Zeichen), MULTIBYTE (variable Zeichengröße) und UNICODE (2 Byte). Allerdings werden die ersten beiden Varianten beide durch char's abgebildet und von vielen Funktionen identisch behandelt.

    Wie kommst Du darauf, dass Unicode 2 Byte sind...

    Unicode als solches definiert nur Codepoints. Diese gehen bis U+10FFFF
    Brauchen also min. 3 Bytes...
    Siehe:
    http://www.fileformat.info/info/unicode/block/index.htm

    I.d.R. wird aber Unicode in einer bestimmten Codierung verwendet. Windows verwendet UTF-16 (ursprünglich UCS2). Viele Unix-Varianten verwenden UTF-8. Beides sind Multibyte-Character-Sets.

    Der einzige nicht Multi-Byte-Character-Set ist UTF-32. Hier kann der Unicode-Zeichensatz (bzw. die Codepoints) direkt abgebildet werden.

    Das ganze heisst aber nicht, dass z.B. ein "ä" aus nur einem Codepoint bestehen muss... ein "ä" kann auch aus mehreren Codepoints bestehen... somit ist auch ein nicht-MBCS keine Garantie dafür, dass man Zeichen direkt findet, die man sucht... aber das war ja nicht das Thema 😉



  • Jochen Kalmbach schrieb:

    CStoll schrieb:

    Es gibt drei verschiedene Zeichensätze - ANSI (1 Byte Zeichen), MULTIBYTE (variable Zeichengröße) und UNICODE (2 Byte). Allerdings werden die ersten beiden Varianten beide durch char's abgebildet und von vielen Funktionen identisch behandelt.

    Wie kommst Du darauf, dass Unicode 2 Byte sind...

    Schlecht geraten und ungenau formuliert (außerdem hat meine Erinnerung für diese Details etwas nachgelassen, seitdem ich micht nicht mehr so oft damit beschäftigen muß).



  • Warum braucht man eigentlich überhaupt so viele Datentypen, wenn es zu fast jedem ein Äquivalent gibt? 😕 Ich meine irgendwo gelesen zu haben, dass DWORD, LPSTR, LPCSTR, etc. von den C-Programmierern übernommen wurden, aber das kann doch unmöglich die Erklärung dafür sein... Wenn man sich die Definitionen der Datentypen anschaut... das ist doch alles doppelt (und manchmal dreifach) gemoppelt..
    Ich meine wozu braucht man PINT wenn's int * bereits gibt?;



  • [Rewind] schrieb:

    Warum braucht man eigentlich überhaupt so viele Datentypen, wenn es zu fast jedem ein Äquivalent gibt? 😕 Ich meine irgendwo gelesen zu haben, dass DWORD, LPSTR, LPCSTR, etc. von den C-Programmierern übernommen wurden, aber das kann doch unmöglich die Erklärung dafür sein... Wenn man sich die Definitionen der Datentypen anschaut... das ist doch alles doppelt (und manchmal dreifach) gemoppelt..
    Ich meine wozu braucht man PINT wenn's int * bereits gibt?;

    Die Frage habe ich mir auch gestellt. Es ist aber nun mal so, dass das meiste noch Überreste aus der 16-Bit-Ära sind, die, um abwärtskompatibilität zu garantieren, drinne sind.



  • Hallo nochmal,

    also auch wenn das jetzt ein bisschen off-topic ist, ich bin seit 2 Jahren als C# Entwickler für Windows-Applikationen tätig und hab auch schon einige Sachen in Java geschrieben. Aber C++ autodidaktisch zu lernen ist echt der absolute Horror.
    Ich komm mir vor als hätte ich noch nie was programmiert. Und die msdn-library ist absolut nicht mein Freund. Ich mein die Doku da ist echt ein bisschen für den .... Es gibt so viele Libraries, für viele gleich mehrere, ein paar noch in C geschrieben... was benutz ich wann. (Bspl. <string> und "String.h").
    Wie 2 Beiträge über mir schon erwähnt, kommt noch erschwerend hinzu, dass es für jeden Datentyp 2 oder mehr "Bezeichungen" gibt.
    Mittlerweile bin ich soweit, dass ich mir wohl ein Buch kaufen werde... Die Grundlagen der Sprache zu lernen war ja kein Problem, aber mit der WINAPI komm ich echt nur schwer voran. Zumindest alles was über WinMain und die Nachrichtenschleife hinausgeht. Im Netz gibts da ja auch nicht wirklich was dazu. 😡

    Ach ja, und nochmal zum Thema:
    Ich hab jetzt in meinem "Lern"-Projekt versucht, meine strings die ich mit WINAPI-Funktionen austauschen muss, als TCHAR zu definieren.
    Wobei ich bei den einfachsten Sachen wieder auf Probleme stoße.
    Bspl. Ich definiere eine variable TCHAR* path und lass mir diese über GetModuleFileName(..) füllen. Funktioniert auch wunderbar. Jetzt würd ich path aber noch gerne abändern mit ein paar Funktionen aus der "String.h" strcpy und so... Jetzt erwarten diese aber wieder eine variable vom Typ char*...

    So, Noobfrage: Ich denke hier muss ich wohl casten, oder?
    Wenn ja, wie? 😕

    Danke an alle die sich meinen kleinen Erguss hier durchlesen und
    vll noch Ihren Senf dazugeben!


Anmelden zum Antworten