Udostępnij za pośrednictwem


TN059: używanie makr konwersji MFC MBCS/Unicode

[!UWAGA]

Następująca uwaga techniczna nie został zaktualizowana od pierwszego uwzględnienia jej w dokumentacji online.W rezultacie niektóre procedury i tematy może być nieaktualne lub nieprawidłowe.Aby uzyskać najnowsze informacje, zaleca się wyszukać temat w indeksie dokumentacji online.

Uwaga ta opisuje sposób używania makra do konwersji MBCS/Unicode, które są zdefiniowane w AFXPRIV.H.Makra te są najbardziej użyteczne, jeśli Twoje oferty aplikacji bezpośrednio z interfejsu API OLE lub z jakiegoś powodu często potrzebuje do konwersji między Unicode i MBCS.

Omówienie

W bibliotece MFC 3.x, specjalne DLL był używany (MFCANS32.DLL) automatycznie konwertować między Unicode i MBCS, gdy były nazywane interfejsy OLE.Ta biblioteka DLL był prawie przezroczysty warstwy, która dozwolonych aplikacji OLE są zapisywane jak gdyby API OLE i interfejsów MBCS, nawet jeśli są one zawsze Unicode (z wyjątkiem komputerów Macintosh).Podczas tej warstwy jest wygodne i dozwolone aplikacje mogą być szybko przenoszone z Win16 do Win32 (MFC, program Microsoft Word, Microsoft Excel i VBA, są tylko niektóre aplikacje firmy Microsoft, które tę technologię), miał wydajności czasami znaczne trafień.Z tego powodu MFC 4.x nie korzysta z tej biblioteki DLL i rozmowy zamiast bezpośrednio do interfejsów Unicode OLE.Aby to zrobić, MFC potrzebuje do konwersji na format Unicode do MBCS podczas nawiązywania połączenia z interfejsem OLE i często wymaga konwersji do MBCS ze standardu Unicode podczas implementacji interfejsów OLE.Aby zapewnić obsługę, wydajne i łatwe, liczba makra zostały utworzone w celu ułatwienia tej konwersji.

Jedną z największych przeszkód tworzenia zestawu makr jest alokacji pamięci.Ponieważ nie można przekonwertować ciągi w miejscu, musi zostać rozdzielona nową pamięć do przechowywania konwertowanych wyników.To może być wykonane z kod podobny 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;

Takie podejście jako liczbę problemów.Głównym problemem jest to, że jest wiele umożliwia pisanie, testowanie i debugowanie kodu.Coś, co było wywołanie funkcji prostego jest teraz znacznie bardziej złożone.Ponadto istnieje znaczny runtime napowietrznych w ten sposób.Pamięci ma zostać przydzielona na stercie i zwalniane każdym razem, gdy jest wykonywana konwersja.Wreszcie, powyższy kod musi dysponować odpowiednią #ifdefs dodane do standardu Unicode i Macintosh buduje (które nie wymagają tej konwersji).

Rozwiązanie, które udało nam się z jest utworzenie niektóre makra, które 1) maska różnicy między różnych platform i 2) Użyj schematu alokacji pamięci efektywne i 3) są łatwo wstawić do istniejących kod źródłowy.Oto przykład jednej z definicji:

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

Za pomocą tego makra zamiast powyższy kod 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 skuteczny.

Wykonania każdego makra użyto funkcji _alloca() przydzielić pamięci ze stosie zamiast stercie.Przydzielanie pamięci ze stosu jest znacznie szybsze niż przydzielania pamięci na stercie, a pamięć jest automatycznie zwalniane, gdy funkcja jest zakończony.Ponadto, makra unikać telefonicznej MultiByteToWideChar (lub WideCharToMultiByte) więcej niż jeden raz.Polega to na przydzielanie trochę więcej pamięci niż jest to konieczne.Zdajemy sobie sprawę, że do co najwyżej jednego przekonwertuje MBC WCHAR i że dla każdego WCHAR będziemy mieć maksymalnie dwa bajty MBC.Przydzielając trochę więcej niż to konieczne, ale zawsze wystarczająco do obsługi konwersji, drugie wywołanie drugie unika się wywołanie funkcji konwersji.Wywołanie funkcji pomocnika AfxA2Whelper zmniejsza ilość suwów argument, które należy wykonać w celu wykonania konwersji (skutkuje to kod mniejszych niż Jeśli go o nazwie MultiByteToWideChar bezpośrednio).

Aby dla makr do miejsca do przechowywania tymczasowych długości, konieczne jest zadeklarować zmienną lokalną o nazwie _convert, który robi to w każdej funkcji że używa makra konwersji.Jest to realizowane przez wywoływania USES_CONVERSION makro, jak widać powyżej w przykładzie.

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

Rodzajowy konwersja makr

Makra rodzajowy konwersji tworzą podstawowy mechanizm.Przykład makro i wykonania pokazano w poprzedniej sekcji, A2W, jest jedno takie makro "Ogólne".To nie jest powiązany OLE w szczególności.Zestaw makr rodzajowy jest poniżej:

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

Poza tym robi konwersji tekstu, istnieją także makr oraz funkcje pomocnika do konwersji TEXTMETRIC, DEVMODE, BSTRi OLE przydzielone ciągów.Makra te wykraczają poza zakres tej dyskusji-odnoszą się do AFXPRIV.H, aby uzyskać 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 badania nagłówki OLE pojawi się wiele odwołań do LPCOLESTR i OLECHAR.Te typy są używane do określenia typów znaków używanych w interfejsów OLE w sposób, który nie jest specyficzny dla platformy.OLECHAR mapy do char w Win16, używających różnych systemów i WCHAR w systemie Win32.

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

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

Ponownie, istnieją podobne makr może TEXTMETRIC, DEVMODE, BSTRi OLE przydzielone ciągów.Odnoszą się do AFXPRIV.H, aby uzyskać więcej informacji.

Inne zagadnienia

Nie należy używać makra w pętlach.Na przykład nie chcesz pisać rodzaju następujący kod:

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

Powyższy kod może skutkować przydzielanie megabajtów pamięci na stosie w zależności od tego, co zawartość ciąg lpsz jest!Również potrzeba czasu, aby przekonwertować ciąg znaków dla każdej iteracji pętli.Zamiast tego przenieść takie 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, a następnie hermetyzacji wywołanie metody do funkcji.Pozwoli to buforu konwersji ma zostać zwolniona każdorazowo.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 zwracają wynik jednego z makr, chyba że wartość zwracana zakłada tworzenie kopii danych przed powrót.Na przykład ten kod 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ższy kod może być ustalona przez zmianę wartości zwracanej do czegoś, 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 łatwe 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 według numerów

Uwagi techniczne według kategorii