Problem with UNICODE: CStringA and CString
-
Hello,
i'm trying to use unicode in my application. The problem is, that i use functions from a non unicode library. Some of these functions expect a CString as an argument, but naturally can't handle UNICODE CStrings.
If i explicitly generate a non unicode CString (CStringA) i cannot compile since a CString (--> CStringT) is expected.
So i guess i'd have to somehow construct a non unicode CStringT in a unicode environment (is that even possible?). Or maybe there is some other workaround?
Thanks
~fog
-
This is a German forum!
CString is a CStringA in a non-Unicode build, and it is CStringW in a unicode build. So you can not saythat CString "naturally" can't handle UNICODE strings!
So CString is something like TCHAR and depends on the flags for _UNICODE!
So if you have a non-UNICODE build and want to use a UNICODE CString, just use CStringW.
-
Erstmal Entschuldigung für den englischen Post, bin so gewöhnt alles im Zusammenhang mit programmieren auf englisch zu machen, dass das so rausgerutscht ist.
Du hast das Problem aber nicht ganz verstanden:
Die Bibliothek ist ohne _UNICODE compiliert, mein Programm mit. Funktionen in der Bibliothek die einen CString übergeben bekommen kann ich nicht mit einem CStringA aufrufen ("Cannot convert from CStringA to CString), und auch nicht mit einem in meinem Code erstelltem CString (gibt nen "unresolved external symbol" linker error).
Compiliere ich meinen Code auch ohne _UNICODE, so funktioniert die Bibliothek reibungslos.
Die Frage ist jetzt, wie kann ich die Bibliothek benutzenm, auch wenn ich selber _UNICODE benutze.
~fog
-
Wenn du selber UNICODE benutzt, hast du CStringW's in deinem Code, die müsstest du im Ernstfall in ANSI-Strings konvertieren, um sie an die Hilfsbibliothek übergeben zu können - dafür gibt's Konvertierungsmakros ala T2A()
-
Ich glaube das Problem ist, dass mein Programm meint, bei "CString" handelt es sich um CStringW und die Bibliothek versteht hallt und "CString" CStringA.
Nun kann ich z.B. keinen LPSTR übergeben, da mein Programm daraus keinen CStringW machen kann, und wenn ich einen LPWSTR übergebe dann kann die Bibliothek, die einen CStringA erwartet, damit nichts anfangen.
Das hilft mir leider auch nicht weiter.
-
Wie gesagt - dafür gibt es Konvertierungsmakros:
USES_KONVERSION;//Hilfdefinitionen ... CString SomeString = ... CString Answer = A2T(SomeExternalFunction(T2A(SomeString)));
-
Ich stelle mich ja wirklich nicht bewusst dumm an, aber das funktioniert bei mir einfach nicht:
libraryObject.setSomeString(T2A(CStringW));
ergibt nachvollziehbar den Compilierfehler "cannot convert parameter 1 from 'LPSTR' to 'CString'"
wie gesagt:
- setSomeString erwartet einen CString
- mein Program meint CString bedeutet CStringW
- Bibliothek meint CString bedeutet CStringA
-
Dann mußt du dem Präprozessor klarmachen, daß für diese Bibliothek andere Regeln gelten, indem du in diesem Header die nötigen #defines für die ANSI-Version rekonstruierst:
#ifdef UNICODE #undef CString #define CString CStringA #endif #include "MyAnsiLib.h" #ifdef UNICODE #undef CString #define CString CStringW #endif
-
Das wäre echt logisch wenn das funktionieren würde.
Tut es aber leider nicht. Habe trotz des CString redefines beim Einbinden der Header Datei der Bibliothek weiterhin den gleichen Compilierfehler.
Er überprüft wohl beim compilieren auf die "CString" Signatur, unabhängig ob der Preprocessor das durch CStringW oder CStringA ersetzt?
(Das würde erklären warum er weiterhin nur akzeptiert, dass ich die Funktion mit einem CStringW aufrufe, mit der diese dann nix anfangen kann. Da innerhalb meines Programmes ja CString CStringW entspricht.)
-
CStringW wstring = L"1234"; libraryObject.setSomeString(CStringA(wstring));
-
Nein, ich kann die Funktion nicht mit CStringA aufrufen.
cannot convert parameter 1 from 'ATL::CStringT<BaseType,StringTraits>' to 'CString' with [ BaseType=char, StringTraits=StrTraitMFC<char> ]Er verlangt dass ich einen CStringW übergebe, da die Signatur der Funktion setSomeString(CString) ist, und innerhalb meines Programmes UNICODE definiert ist.
-
Da bleibt dir wohl nichts anderes übrig, als den Bibliotheksheader an deine Bedürfnisse anzupassen (sprich: alle Vorkommen von CString durch CStringA ersetzen) und diesen Ersatzheader einzubinden. Oder - wenn verfügbar - du compilierst die Bibliothek nochmal neu im UNICODE-Modus.
(die Probleme mit UNICODE sind schon alleine schlimm genug - durch die Vermischung von ANSI und UNICODE machst du alles nur noch schlimmer)
-
OK, danke für die Antworten.
Ist wohl dann am einfachsten einen Wrapper für die Bibliothek zu schreiben, auch wenn ich das eigentlich vermeiden wollte.
Die Bibliothek komplett in UNICODE zu compilieren ist theoretisch auch möglich, aber die hatt schon wieder so viele Abhängigkeiten, dass ich da eigentlich gar nicht drann will.
Falls doch noch jemand einen Trick kennt mit dem sich der Compiler zufriedenstellen lässt außer die beiden erwähnten Möglichkeiten bin ich natürlich für weitere Vorschläge dankbar.
Grüße ~fog
-
Du könntest auch deine Anwendung im ANSI-Modus compilieren.
-
Man könnte auch einfach vor dem besagtem Header include ein
#define CString CStringA #include "AnySillyLibUsingCStringAsAgrument.h" #undef CStringmachen...
BTW: Wenn die EXE und die DLL/LIB nicht die selbe CRT und MFC verwenden, dann rennst Du sowieso in Teufels Küche...
-
Ja, das ist natürlich das einfachste. Das funktioniert auch problemlos. Aber es soll halt unicode unterstützt werden, also habe ich diese Wahl nicht.
-
Martin Richter schrieb:
Man könnte auch einfach vor dem besagtem Header include ein
#define CString CStringA #include "AnySillyLibUsingCStringAsAgrument.h" #undef CStringmachen...
BTW: Wenn die EXE und die DLL/LIB nicht die selbe CRT und MFC verwenden, dann rennst Du sowieso in Teufels Küche...
So etwas hat CStoll schon vorgeschlagen. Das funktioniert nicht, da er beim Aufruf einer library Funktion aus dem Programm weiterhin auf CStringW besteht, also CString als Signatur der Funktion hat, nicht CStringA.
-
Es gibt keine Signatur CString!
CString ist ein typedef auf
typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;Und dieser ist damit entweder:
typedef ATL::CStringT< wchar_t, StrTraitMFC_DLL< wchar_t > > CStringW;
typedef ATL::CStringT< char, StrTraitMFC_DLL< char > > CStringA;Punkt!
-
Uhmm... jup, du hast recht.
Ich habe mich durch die Compilermeldungen verwirren lassen. Irgendwie konnte ich mir nur so erklären, dass er die Funktionen die ich mit CString in der Bibliothek aufgerufen habe nicht gefunden hat, Funktionen ohne CString Parameter aber schon.
Tatsächlich lag es daran, dass in den beiden Projekten die Einstellung "treat wchar as build in type" unterschiedlich eingestellt war.
Tut mir leid, dass ich hier falsche Sachen erzählt habe, benutze zum ersten mal unicode / wchar und hab mich gleich ganz schön verrannt.