Diese Applikationsschrift beschreibt, wie die Makros für MBCS/Unicode-Konvertierung, die in AFXPRIV definiert sind.H. diese Makros sind besonders hilfreich, wenn Ihre Anwendung Geschäfte direkt mit der OLE-API oder aus irgendeinem Grund, oft muss Konvertierung zwischen Unicode und MBCS.
Übersicht
In MFC 3.x, wurde eine spezielle DLL verwendet (MFCANS32.DLL) automatisch konvertieren zwischen Unicode und MBCS, wenn OLE-Schnittstellen aufgerufen wurden. Diese DLL-Datei wurde eine fast transparente Schicht, die OLE-Anwendungen geschrieben werden, als wären die OLE-APIs und Schnittstellen MBCS, obwohl sie immer Unicode sind zulässig (außer auf dem Macintosh). Während dieser Schicht bequem war und erlaubt Anwendungen schnell von Win16 auf Win32 portieren (MFC, Microsoft Word, Microsoft Excel und VBA, sind nur einige der Microsoft-Anwendungen, die diese Technologie verwendet), es hatte auch manchmal die Performance schlagen. Aus diesem Grund MFC 4.x verwendet diese DLL nicht und stattdessen kommuniziert direkt mit der Unicode-OLE-Schnittstellen. Um dies zu tun, MFC konvertieren in Unicode zu MBCS beim Telefonieren in eine OLE-Schnittstelle muss, und muss oft in MBCS aus Unicode konvertiert, wenn eine OLE-Schnittstelle implementieren. Um dies effizient und einfach zu behandeln, wurden eine Reihe von Makros erstellt, um diese Konvertierung zu erleichtern.
Eine der größten Hürden schaffen so eine Reihe von Makros ist die Speicherzuweisung. Da die Zeichenfolgen im Ort konvertiert werden können, muss neuer Speicher für die konvertierten Ergebnisse zugeordnet werden. Dies könnte mit Code ähnlich dem folgenden getan haben:
/ / Wir wollen eine MBCS-Zeichenfolge in LpszA konvertieren
Int nLen = MultiByteToWideChar (CP_ACP, 0, LpszA, 1, NULL, NULL);
LPWSTR LpszW = neue WCHAR [nLen];
MultiByteToWideChar (CP_ACP, 0, LpszA, 1, LpszW, nLen);
/ / Hier Aufrufen von OLE verwenden
pI-≫SomeFunctionThatNeedsUnicode(lpszW);
/ / den String free
Löschen [] lpszW
Dieser Ansatz als eine Reihe von Problemen. Das Hauptproblem ist, dass es eine Menge Code schreiben, testen und Debuggen. Etwas, das einen einfachen Funktionsaufruf war, ist jetzt sehr viel komplexer. Darüber hinaus gibt es eine wichtige Common Language Runtime Aufwand dabei. Speicher hat auf dem Heap reserviert und freigegeben, jedes Mal, wenn eine Konvertierung erfolgt. Schließlich, der obigen Code würde benötigen die entsprechenden #ifdefs für Unicode und Macintosh Builds (die Konvertierung stattfinden nicht erforderlich).
Die Lösung kamen wir mit ist um einige Makros zu erstellen, welche 1) Maske der Unterschied zwischen den verschiedenen Plattformen, und 2) Verwendung eine effiziente Speicher Zuweisung Schema, und 3) sind einfach zum Einfügen in die vorhandene-Code Quell. Hier ist ein Beispiel für eine der Definitionen:
# define A2W(lpa) (\
&Nbsp; ((LPCSTR) Lpa == NULL)? NULL: (\
_convert = (Strlen (Lpa) + 1), \
AfxA2WHelper((LPWSTR) alloca(_convert*2), Lpa, _convert) \
)\
)
Mit diesem Makro anstelle des obigen Codes und die Dinge sind viel einfacher:
/ / Hier Aufrufen von OLE verwenden
DAS USES_CONVERSION;
pI-≫SomeFunctionThatNeedsUnicode(T2OLE(lpszA))
Es gibt zusätzliche Anrufe wo Konvertierung ist notwendig, aber mit den Makros ist einfach und effektiv.
Die Umsetzung der jedes Makro verwendet die _alloca()-Funktion aus dem Stapel statt dem Heap Speicher zuordnen. Reservieren von Speicher im Stapel ist viel schneller als beim Zuweisen von Speicher auf dem Heap, und der Speicher wird automatisch freigegeben, wenn die Funktion beendet wird. Darüber hinaus, die Makros zu vermeiden Aufrufen von MultiByteToWideChar (oder WideCharToMultiByte) mehr als einmal. Dies ist ein bisschen mehr Speicher als nötig. Wir wissen, dass höchstens eine WCHAR ein MBC umgewandelt wird und dass für jede WCHAR haben wir ein Maximum von zwei Bytes, MBC wird. Durch Zuteilung von ein wenig mehr als nötig, aber immer genug ist, der Umwandlung den zweiten Aufruf Zweitens behandeln Aufforderung der Konvertierungsfunktion vermieden. Der Aufruf der Hilfsfunktion AfxA2Whelper reduziert die Anzahl der Argument schiebt, die was getan werden muss, um die Konvertierung durchführen (Dies führt zu kleineren Code, als wenn es MultiByteToWideChar direkt aufgerufen).
In Reihenfolge für die Makros, Raum haben zum Speichern der temporären Länge, ist es notwendig, deklarieren Sie eine lokale Variable namens _convert, das dies in jeder Funktion, dass die Konvertierung Makros verwendet. Dies geschieht durch das USES_CONVERSION -Makro aufrufen, wie im Beispiel oben gesehen.
Es gibt generische Konvertierung Makros und OLE spezifische Makros. Diese zwei verschiedenen Makro-Sets werden nachstehend erläutert. Alle Makros befinden sich im AFXPRIV.H.
Generische Konvertierung Makros
Die generische Konvertierung Makros bilden den zugrunde liegende Mechanismus. Die Makro-Beispiel und Umsetzung angezeigt, die im vorherigen Abschnitt, A2W, ist eine solche "generischen" Makro. Es hat keinen Bezug zu OLE speziell. Der Satz von generischen Makros sind unten aufgeführt.:
A2CW (LPCSTR) - Gt; (LPCWSTR)
A2W (LPCSTR) - > (LPWSTR)
W2CA (LPCWSTR) - > (LPCSTR)
W2A (LPCWSTR) - > (LPSTR)
Neben Text Konvertierungen zu tun, es gibt auch Makros und Hilfsfunktionen zum Konvertieren von OLE TEXTMETRIC, DEVMODEund BSTRZeichenfolgen zugeordnet. Diese Makros sind nicht Gegenstand dieser Diskussion – beziehen sich auf AFXPRIV.H für weitere Informationen über die Makros.
OLE Konvertierung Makros
Der OLE-Konvertierung Makros sind entwickelt für den Umgang mit Funktionen die OLESTR Zeichen erwarten. Wenn Sie den OLE-Header untersuchen, sehen Sie viele Verweise auf LPCOLESTR und OLECHAR. Diese Typen werden zum Verweisen auf den Typ von Zeichen, die in OLE-Schnittstellen in einer Weise, die nicht spezifisch für die Plattform verwendet. OLECHAR Char in Win16 und Macintosh-Plattformen und WCHAR in Win32 zugeordnet.
Um die Anzahl der # ifdef -Direktiven in den MFC-Code auf ein Minimum zu halten haben wir eine ähnliche Makro für jede Konvertierung, wo OLE Streicher beteiligt sind. Die folgenden Makros sind die am häufigsten verwendeten:
T2COLE (LPCTSTR) - Gt; (LPCOLESTR)
T2OLE (LPCTSTR) - > (LPOLESTR)
OLE2CT (LPCOLESTR) - > (LPCTSTR)
OLE2T (LPCOLESTR) - > (LPCSTR)
Wieder gibt es ähnliche Makros dafür TEXTMETRIC, DEVMODEund OLE BSTRZeichenfolgen zugeordnet. Finden Sie unter AFXPRIV.H Weitere Informationen.
Weitere Überlegungen
Verwenden Sie die Makros nicht in einer engen Schleife. Beispielsweise wollen Sie nicht auf die folgende Art von Code schreiben:
void BadIterateCode(LPCTSTR lpsz)
{
DAS USES_CONVERSION;
für (Int Ii = 0; Ii Lt; 10000; Ii ++)
pI - > SomeMethod (Ii, T2COLE(lpsz));
}
Der obigen Code könnte bei der Zuteilung von Megabyte Speicher auf dem Stapel abhängig vom Inhalt der Zeichenfolge lpsz ist! &Nbsp; Es braucht auch Zeit um die Zeichenfolge für jede Iteration der Schleife zu konvertieren. Stattdessen verschieben Sie solche ständigen Konvertierungen aus der Schleife:
void MuchBetterIterateCode(LPCTSTR lpsz)
{
DAS USES_CONVERSION;
LPCOLESTR LpszT = T2COLE(lpsz);
für (Int Ii = 0; Ii Lt; 10000; Ii ++)
pI - > SomeMethod (Ii, LpszT);
}
Wenn die Zeichenfolge nicht konstant ist, dann Kapseln des Methodenaufrufs in eine Funktion. Dadurch wird den Konvertierung-Puffer zu jeder Zeit freigegeben werden. Zum Beispiel:
void CallSomeMethod (Int Ii, LPCTSTR Lpsz)
{
DAS USES_CONVERSION;
pI-Gt;SomeMethod (Ii, T2COLE(lpsz));
}
void MuchBetterIterateCode2 (LPCTSTR LpszArray)
{
für (Int Ii = 0; Ii < 10000 Ii ++)
CallSomeMethod (Ii, lpszArray[ii]);
}
Niemals das Ergebnis eines der Makros, zurück, wenn der Rückgabewert bedeutet eine Kopie der Daten vor der Rückkehr. Dieser Code ist beispielsweise schlecht:
LPTSTR BadConvert(ISomeInterface* pI)
{
DAS USES_CONVERSION;
LPOLESTR Lpsz = NULL;
pI-Gt;GetFileName(&lpsz);
LPTSTR LpszT = OLE2T(lpsz);
CoMemFree(lpsz);
Rückkehr LpszT; / / bad! wiederkehrende Alloca-Speicher
}
Der obige Code konnte behoben werden, indem Sie den Rückgabewert auf etwas, das den Wert kopiert:
CString BetterConvert(ISomeInterface* pI)
{
DAS USES_CONVERSION;
LPOLESTR Lpsz = NULL;
pI-Gt;GetFileName(&lpsz);
LPTSTR LpszT = OLE2T(lpsz);
CoMemFree(lpsz);
Rückkehr LpszT; / / CString macht Kopie
}
Die Makros sind einfach zu bedienen und einfach in Ihren Code einfügen, aber wie Sie aus den oben genannten Einschränkungen sagen können, Sie müssen vorsichtig sein, wenn sie mit.
Technische Hinweise von &Nummer |nbsp; Technische Hinweise nach Kategorie