Udostępnij za pośrednictwem


TN059: Za pomocą makra konwersji MFC MBCS/Unicode

[!UWAGA]

Następujące Uwaga techniczna została zaktualizowana, ponieważ najpierw została uwzględniona w dokumentacji online.W rezultacie niektóre procedur i tematów może być nieaktualne lub nieprawidłowe.Najnowsze informacje zaleca się wyszukać temat zainteresowanie Indeks dokumentacji online.

Uwaga Ta informacje dotyczące używania makra do konwersji MBCS/Unicode, które są zdefiniowane w AFXPRIV.H.Te makra są najbardziej przydatne, jeśli Twoje oferty aplikacji bezpośrednio z OLE API lub z jakiegoś powodu często wymaga konwersji między Unicode i MBCS.

Omówienie

W MFC 3.x DLL specjalne był używany (MFCANS32.Biblioteka DLL) automatycznie konwersji między Unicode i MBCS, kiedy były nazywane interfejsy OLE.Ta biblioteka DLL był prawie przezroczysty warstwy, która dozwolone aplikacje OLE są zapisywane jak gdyby API OLE i interfejsów MBCS, mimo że są one zawsze Unicode (z wyjątkiem komputerów Macintosh).Gdy warstwa ta była wygodny i dozwolone aplikacje mogą szybko być przenoszone do systemu Win32 Win16 (MFC, program Microsoft Word, Microsoft Excel i VBA, są tylko niektóre aplikacje firmy Microsoft, które używane tej technologii), miał on niekiedy znacznie zwiększyć wydajność trafień.Z tego powodu MFC 4.x nie korzysta z tej biblioteki DLL i zamiast rozmawiało bezpośrednio interfejsy Unicode OLE.Aby to zrobić, MFC musi przekonwertować na Unicode do MBCS podczas nawiązywania połączenia z interfejsem OLE i często musi przekonwertować MBCS ze standardu Unicode podczas wdrażania interfejsu OLE.Do obsługi, efektywne i łatwe, liczba makra zostały utworzone w celu ułatwienia tej konwersji.

Jednym z największych progi tworzenia zestawu makr jest alokacji pamięci.Ponieważ nie można przekonwertować ciągi w miejscu, musi zostać rozdzielona nowa pamięć do przechowywania wyników przekonwertowane.To może mieć zostały wykonane przy użyciu kodu podobnego do następującego:

// we want to convert an MBCS string in lpszA
int nLen = MultiByteToWideChar(CP_ACP, 0,lpszA, -1, NULL, NULL);
LPWSTR lpszW = new WCHAR[nLen];
MultiByteToWideChar(CP_ACP, 0, 
   lpszA, -1, lpszW, nLen);
// use it to call OLE here
pI->SomeFunctionThatNeedsUnicode(lpszW);
// free the string
delete[] lpszW;

To podejście jako liczbę problemów.Głównym problemem jest to, że jest dużo kodu do zapisu, testowania i debugowania.Coś, co zostało wywołanie funkcji prostego jest teraz znacznie bardziej skomplikowane.Dodatkowo istnieją znaczące runtime napowietrznej w ten sposób.Pamięć ma być przydzielone na stercie i zwalniane po każdym zakończeniu konwersji.Wreszcie, kod powyżej musi dysponować odpowiednią #ifdefs dodane do standardu Unicode i Macintosh kompilacje (które nie wymagają tej konwersji na miejsce).

Rozwiązanie, które możemy dostarczyły jest utworzenie niektóre makra, które 1) maski różnica między różnymi platformami i 2) Użyj programu alokacji pamięci efektywne i 3) są łatwo wstawić istniejący kod źródłowy.Oto przykład jednego z definicjami:

#define A2W(lpa) (\
    ((LPCSTR)lpa == NULL) ? NULL : (\
          _convert = (strnlen(lpa)+1),\
        AfxA2WHelper((LPWSTR) alloca(_convert*2), 
      lpa, _convert)\
    )\
)

Za pomocą tego makra, zamiast powyższego kodu i rzeczy jest znacznie prostsze:

// use it to call OLE here
USES_CONVERSION;
pI->SomeFunctionThatNeedsUnicode(T2OLE(lpszA));

Istnieją dodatkowe wywołania, gdzie konwersji jest konieczne, ale przy użyciu makr jest prosty i efektywny.

Wykonania każdego makra użyto funkcji _alloca() przydzielić pamięci z stosie zamiast stercie.Alokowanie pamięci ze stosu jest znacznie szybsze niż przydzielania pamięci na stercie, a pamięć jest automatycznie zwalniana, gdy funkcja jest zakończony.Ponadto makra uniknąć wywołania MultiByteToWideChar (lub WideCharToMultiByte) więcej niż jeden raz.Polega to na przydzielanie trochę więcej pamięci niż jest to konieczne.Wiemy, że MBC będzie przekonwertować najwyżej jedną WCHAR i że dla każdego WCHAR będziemy mieć maksymalnie dwa bajty MBC.Przydzielając trochę więcej niż jest to konieczne, ale zawsze wystarczająco do obsługi konwersji, drugie wywołanie drugi unika się wywołanie funkcji konwersji.Wywołanie funkcji pomocnika AfxA2Whelper zmniejsza ilość suwów argument, które muszą być wykonane na przeprowadzenie konwersji (powoduje to kod mniejszych niż Jeśli jest on nazywany MultiByteToWideChar bezpośrednio).

W celu makr do miejsca do przechowywania tymczasowych długości, należy zadeklarować zmiennej lokalnej o nazwie _convert, który robi to w każdej funkcji, która używa makra konwersji.Jest to realizowane przez wywoływanie USES_CONVERSION makro, jak pokazano powyżej.

Istnieją zarówno rodzajowy konwersja makr i OLE określonego makra.Te dwa zestawy innego makra są omówione poniżej.Wszystkie makra znajdują się w AFXPRIV.H.

Rodzajowy konwersja makr

Makra rodzajowy konwersji formularza mechanizm podstawowej.Przykład makro i wykonania przedstawione w poprzedniej sekcji, A2W, jest jedno takie makro "ogólny".Nie jest powiązany z OLE specjalnie.Zestaw rodzajowy makr jest wymienionych poniżej:

A2CW      (LPCSTR) -> (LPCWSTR)
A2W      (LPCSTR) -> (LPWSTR)
W2CA      (LPCWSTR) -> (LPCSTR)
W2A      (LPCWSTR) -> (LPSTR)

Oprócz wykonywania konwersji tekstu, są również makra i funkcje pomocnika do konwersji TEXTMETRIC, DEVMODE, BSTRi OLE przydzielone ciągi.Te makra są poza zakres tej dyskusji — odnoszą się do AFXPRIV.H więcej informacji na temat tych makr.

OLE konwersja makr

Makra konwersji OLE są zaprojektowane specjalnie do obsługi funkcji, które oczekują, że OLESTR znaków.Jeśli zbadamy nagłówki OLE będzie Zobacz wiele odwołań do LPCOLESTR i OLECHAR.Te typy są używane do odwoływania się do typ znaków używanych w interfejsów OLE w sposób, który nie jest specyficzne dla platformy.OLECHAR mapy do char na platformach Macintosh, jak i Win16 i WCHAR w systemie Win32.

Aby zachować liczby # ifdef dyrektyw w MFC kodu do minimum mamy podobne makro dla każdej konwersji, gdy zaangażowane są ciągi OLE.Najczęściej są używane następujące makra:

T2COLE   (LPCTSTR) -> (LPCOLESTR)
T2OLE   (LPCTSTR) -> (LPOLESTR)
OLE2CT   (LPCOLESTR) -> (LPCTSTR)
OLE2T   (LPCOLESTR) -> (LPCSTR)

Ponownie, istnieją podobne makra w tym TEXTMETRIC, DEVMODE, BSTRi OLE przydzielone ciągi.Odnoszą się do AFXPRIV.H, aby uzyskać więcej informacji.

Inne uwagi

Nie należy używać makr ścisła pętli.Na przykład nie chcesz zapisać rodzaj następujący kod:

void BadIterateCode(LPCTSTR lpsz)
{
   USES_CONVERSION;
   for (int ii = 0; ii < 10000; ii++)
      pI->SomeMethod(ii, T2COLE(lpsz));
}

Kod powyżej może skutkować przydzielania megabajtów pamięci na stosie w zależności od tego, jakie zawartości ciągu lpsz jest!Również czas konwersji ciągu znaków dla każdej iteracji pętli.Zamiast tego Przenieś takich stałej konwersje z pętli:

void MuchBetterIterateCode(LPCTSTR lpsz)
{
   USES_CONVERSION;
   LPCOLESTR lpszT = T2COLE(lpsz);
   for (int ii = 0; ii < 10000; ii++)
      pI->SomeMethod(ii, lpszT);
}

Jeśli ciąg nie jest stała, następnie hermetyzowania wywołanie metody do funkcji.Umożliwi to buforu konwersji na każdym zwolniona.Na przykład:

void CallSomeMethod(int ii, LPCTSTR lpsz)
{
   USES_CONVERSION;
   pI->SomeMethod(ii, T2COLE(lpsz));
}

void MuchBetterIterateCode2(LPCTSTR* lpszArray)
{
   for (int ii = 0; ii < 10000; ii++)
      CallSomeMethod(ii, lpszArray[ii]);
}

Nigdy nie zwraca wynik jednego z makr, chyba, że zwracana wartość oznacza kopii danych przed powrotu.Na przykład kod ten jest zły:

LPTSTR BadConvert(ISomeInterface* pI)
{
   USES_CONVERSION;
   LPOLESTR lpsz = NULL;
   pI->GetFileName(&lpsz);
   LPTSTR lpszT = OLE2T(lpsz);
   CoMemFree(lpsz);
   return lpszT; // bad! returning alloca memory
}

Powyższego kodu może ustalić zmieniając wartość zwracana na coś, co kopiuje wartość:

CString BetterConvert(ISomeInterface* pI)
{
   USES_CONVERSION;
   LPOLESTR lpsz = NULL;
   pI->GetFileName(&lpsz);
   LPTSTR lpszT = OLE2T(lpsz);
   CoMemFree(lpsz);
   return lpszT; // CString makes copy
}

Makra są łatwe w użyciu i łatwa do wstawienia do kodu, ale jak widać z powyższego ostrzeżenia, należy zachować ostrożność podczas ich używania.

Zobacz też

Inne zasoby

Uwagi techniczne przez liczbę

Uwagi techniczne według kategorii