Wie vermeide ich Redundanzen bei Funktionen für LPCSTR, LPCTSTR und LPCWSTR?
-
Hast Du zu der Klasse eine LIB/DLL, oder wird der Source direkt verwendet?
-
Wenn ich sie selbst verwende, benutze ich natürlich die Header- und CPP-Datei direkt. Wenn ich das Ding mal online stelle (es fehlen noch die Kommentare im Code), dann muß ich mir überlegen, ob ich den Quellcode freigebe oder eine Lib daraus mache.
Würde es einen Unterschied machen, ob man nun die CPP- oder die Lib-Datei benutzt? (Diese Variante, daß ich je nach Option eine andere Lib-Datei einbinde, würde ich nämlich nicht bevorzugen.)Noch eine Frage: Du hast einerseits
Die Umwandling von ANSI nach Unicode erfolgt hier mittels RtlInitAnsiString und RtlAnsiStringToUnicodeString.
und andererseits
SOnst ist die schnelleste Methode die Verwendung von "MultiByteToWideChar" (das verwenden intern zumindest alle mir bekannten Funktionen).
geschrieben. Welche Version ist denn jetzt die, die die WinAPI selbst nutzt?
-
Wenn Du die cpp direkt verwendest, dann brauchst Du *nur* die TCHAR Version!
Auch wenn Du eine LIB zur Verfügung stellst (jeweils eine für Ansi und eine für Unicode) brauchst Du *nur* die TCHAR Version! Auch wenn Du eine DLL für Ansi und eine für Unicode zur Verfügung stellst brauchst Du *nur* die TCHAR Version!
Fazit: Mach nur TCHAR und entscheide später was Du weitergeben willst.
-
Nur TCHAR machen würde ja an sich gehen, wenn die generelle Unicode-Fähigkeit des Programms allein durch das Makro festgelegt werden würde. Aber man kann ja Unicode auch benutzen, wenn das Makro ausgeschaltet ist, indem man direkt den Wide String verwendet. Was ist nun, wenn jemand irgendwelche Spielchen wie folgendes machen will:
//#define UNICODE #include <string> #include <windows.h> using namespace std; typedef basic_string<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > tstring; int WINAPI WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { string textA="Ohne Unicode"; wstring textW=L"Mit Unicode"; tstring text=TEXT ("Je nachdem"); textW [0]=0x5DE; #ifdef UNICODE text [0]=0x5D9; #endif MessageBoxA (NULL, textA.c_str (), "MB", MB_OK); MessageBoxW (NULL, textW.c_str (), L"MB", MB_OK); MessageBox (NULL, text.c_str (), TEXT ("MB"), MB_OK); }Somit muß ich immer alle drei Varianten einbauen.
Ich hab übrigens meinen Eintrag von oben nochmal editiert. Da steht noch die Frage:
Du hast einerseits
Die Umwandling von ANSI nach Unicode erfolgt hier mittels RtlInitAnsiString und RtlAnsiStringToUnicodeString.
und andererseits
SOnst ist die schnelleste Methode die Verwendung von "MultiByteToWideChar" (das verwenden intern zumindest alle mir bekannten Funktionen).
geschrieben. Welche Version ist denn jetzt die, die die WinAPI selbst nutzt?
-
Was ist nun, wenn jemand irgendwelche Spielchen wie folgendes machen will:
Was für ein Kuddelmuddel.
Wenn Du meinst, der Benutzer benötigt wirklich beide Varianten: bau Dir eine einfache Stringklasse als Übergabeparameter für Deine Funktionen, die jede der beiden Textvarianten aufnehmen und (auch die jeweils andere nach interner Konvertierung) ausgeben kann.
-
Danke, aber ich habe mich jetzt für folgendes entschieden: Ich schreibe zwei Funktionen, eine für Strings, eine für WStrings. Das Makro
#ifdef UNICODE #define MeineFunktion MeineFunktionW #else #define MeineFunktion MeineFunktionA #endiflaß ich weg. Dafür haben beide Funktionen den gleichen Namen, ein Vorteil, den es in C ja nicht gibt, in C++ aber schon. Und das ganze sieht dann so aus:
void MeineFunktion (LPCSTR text); void MeineFunktion (LPCWSTR text);Jetzt kann der Benutzer den Datentyp nehmen, den er will (LPCSTR, LPCTSTR oder LPCWSTR) und braucht nur einen Funktionsnamen aufzurufen.
Und wie das Umwandeln geht, weiß ich jetzt auch, so daß die normale Funktion dann den String umwandelt und einfach nur die Unicode-Funktion aufruft.
-
Ist aber nicht unbedingt sinnvoll, da Du dann beispielsweise auch UNICODE-Funktionscode dabei hast, obwohl Du auf ANSI-Zeichensatz compilierst, aber hängt natürlich vom Kontext ab
.
-
Genau so ist es ja auch gedacht: Wenn der Benutzer das nehmen will, was durch das Definieren oder nicht Definieren des UNICODE-Makros angedacht ist, dann nimmt er den Datentyp LPCTSTR und der Compiler sucht die richtige Funktion aus. Wenn er etwas unabhängig von diesem Makro machen will, nimmt er entsprechend LPCSTR oder LPCWSTR.
Es geht mir einfach nur darum, daß in meinen Funktionen genau das möglich ist, was auch mit den Original-Windows-Funktionen möglich ist: Man kann zwar dieses Makro festlegen, um generell zu sagen, ob man nun standardmäßig mit Unicode arbeiten will oder nicht, aber trotzdem kann man das Makro auch an gewissen Stellen ignorieren, wie in der WinAPI, wenn man direkt mit den A- oder W-Funktionen arbeitet.
Ich meine, hätte man gewollt, daß es immer vom Unicode-Makro abhängt und man dieses nicht übergehen kann, hätte man die A- und W-Funktionen ja ausschließlich in den ursprünglichen C-Dateien definieren können und das, was jetzt das Makro ist, wäre dann eine richtige Funktion, etwa so:Header-Datei:
int MessageBox (HWND hWnd, LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType);Quellcode-Datei:
int MessageBoxA (HWND hWnd, LPCSTR lpszText, LPCSTR lpszCaption, UINT nType); int MessageBoxW (HWND hWnd, LPCWSTR lpszText, LPCWSTR lpszCaption, UINT nType); int MessageBox (HWND hWnd, LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType) { return #ifdef UNICODE MessageBoxW #else MessageBoxA #endif (hWnd, lpszText, lpszCaption, nType); } int MessageBoxA (HWND hWnd, LPCSTR lpszText, LPCSTR lpszCaption, UINT nType) { //Blablabla } int MessageBoxW (HWND hWnd, LPCWSTR lpszText, LPCWSTR lpszCaption, UINT nType) { //Blablabla }Aber nein, der Benutzer hat vollen Zugriff auf alle drei Versionen und kann sowohl abhängig, als auch unabhängig vom Unicode-Makro arbeiten. Das gleiche soll bei mir auch möglich sein.
-
Ich meine, hätte man gewollt, daß es immer vom Unicode-Makro abhängt und man dieses nicht übergehen kann, hätte man die A- und W-Funktionen ja ausschließlich in den ursprünglichen C-Dateien definieren können und das, was jetzt das Makro ist, wäre dann eine richtige Funktion
Nein, denn bei Funktionen, die sich nur im Rückgabetyp unterscheiden, funktioniert das Überladen nicht.
-
Ich wiederhole mich einfach mal, dann weißt Du, das Dein Post eigentlich überflüssig war
, aber ist nicht böse gemeint (hoffe das kommt nicht so an
).CodeFinder schrieb:
[...] aber hängt natürlich vom Kontext ab
.mgs_ schrieb:
Ich meine, hätte man gewollt, daß es immer vom Unicode-Makro abhängt und man dieses nicht übergehen kann, hätte man die A- und W-Funktionen ja ausschließlich in den ursprünglichen C-Dateien definieren können und das, was jetzt das Makro ist, wäre dann eine richtige Funktion
Nein, denn bei Funktionen, die sich nur im Rückgabetyp unterscheiden, funktioniert das Überladen nicht.
Das stimmt zwar, aber Seine Parameter sind ja verschieden (LPCSTR != LPCWSTR).
-
Zunächst mal kann in c sowieso nicht überladen werden, und die WinApi-Schnittstelle ist in c realisiert.
Aber selbst in c++ funktioniert Polymorphismus nur für Aufrufparameter, nicht für Rückgabeparameter. Wenn zwei gleichnamige Api-Funktionen sich nur im Rückgabeparameter unterscheiden (TCHAR, d. h. char und wchar), ist Überladung nicht möglich.
-
Zunächst mal kann in c sowieso nicht überladen werden, und die WinApi-Schnittstelle ist in c realisiert.
Deshalb habe ich ja auch von meinen eigenen Funktionen gesprochen, die definitiv in C++ geschrieben werden.
Aber selbst in c++ funktioniert Polymorphismus nur für Aufrufparameter, nicht für Rückgabeparameter. Wenn zwei gleichnamige Api-Funktionen sich nur im Rückgabeparameter unterscheiden (TCHAR, d. h. char und wchar), ist Überladung nicht möglich.
So ist es ja bei mir auch nicht:
void MeineFunktion (LPCSTR text); void MeineFunktion (LPCWSTR text);Verschiedene Aufrufparameter. (Und der Rückgabewert ist hier nichtmal anders.)
-
Wozu braucht man noch was anderes als Unicode ?
-
Damit ich einem Benutzer von Windows 95/98 nicht sagen muß: "Bitte update Dein Betriebssystem auf Windows 2000 oder höher, um mein 50 KB großes Programm zu starten." Ach ja, und damit ich selbst meine Anwendungen benutzen kann (Windows 98).

-
-
Und damit ich für meine Anwendungen nicht irgendwelche fetten DLL-Dateien mitliefern bzw. statisch linken muß. (Erst recht nicht, wenn Unicode eigentlich gar nicht gebraucht wird. Ich meine, ich benutze in meinen Programmen ja nicht ständig zum Beispiel die japanische Sprache.)
Außerdem will ich den Benutzern meiner allgemeinen Quellcodes/Libs nicht sagen müssen, daß sie erst so einen Layer runterladen sollen, um 50 KB große Programme zu schreiben.
-
@NES-Spieler: Jo Deinem letzten Post kann ich nur zustimmen, seh ich genau so.
@mgs_: Ich hoffe Du weißt jetzt, was ich meinte
.
-
@NES-Spieler und Codefinder
Meine Ausführungen zum Überladen bezogen sich auf NES-Spielers Argument:Ich meine, hätte man [... bei Microsoft ...] gewollt, daß es immer vom Unicode-Makro abhängt und man dieses nicht übergehen kann, hätte man die A- und W-Funktionen ja ausschließlich in den ursprünglichen C-Dateien definieren können und das, was jetzt das Makro ist, wäre dann eine richtige Funktion
Ich habe lediglich eine sinnvollere Begründung dafür genannt, dass Microsoft diese Makros verwendet. Ein Überladen wäre eben nicht möglich gewesen.
-
Ich habe lediglich eine sinnvollere Begründung dafür genannt, dass Microsoft diese Makros verwendet. Ein Überladen wäre eben nicht möglich gewesen.
Ich habe auch nicht davon gesprochen, dass Microsoft die Funktionen hätten überladen können, wenn sie gewollt hätten, daß alles vom UNICODE-Makro abhängt, sondern meine Denkweise war so: Hätte Microsoft gewollt, daß die Verwendung von Unicode ausschließlich vom UNICODE-Makro abhängt und nicht auch individuell getätigt werden kann, dann hätten sie auf die Funktions-Makros verzichten und ihren Code so schreiben können:
Header-Datei:
int MessageBox (HWND hWnd, LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType);Quellcode-Datei (C-Datei):
int MessageBoxA (HWND hWnd, LPCSTR lpszText, LPCSTR lpszCaption, UINT nType); int MessageBoxW (HWND hWnd, LPCWSTR lpszText, LPCWSTR lpszCaption, UINT nType); int MessageBox (HWND hWnd, LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType) { return #ifdef UNICODE MessageBoxW #else MessageBoxA #endif (hWnd, lpszText, lpszCaption, nType); } int MessageBoxA (HWND hWnd, LPCSTR lpszText, LPCSTR lpszCaption, UINT nType) { //Blablabla } int MessageBoxW (HWND hWnd, LPCWSTR lpszText, LPCWSTR lpszCaption, UINT nType) { //Blablabla }