Aracılığıyla paylaş


TN059: mfc mbcs/Unicode dönüştürme makroları kullanma

[!NOT]

İlk çevrimiçi belgelerinde yer almıştır beri aşağıdaki teknik Not güncelleştirilmedi.Sonuç olarak bazı yordamlar ve konuları eski veya yanlış.En son bilgiler için çevrimiçi belgelere dizini ilgilendiğiniz konu aramak önerilir.

Bu not, AFXPRIV içinde tanımlanan mbcs/Unicode dönüştürme makroları kullanmayı açıklamaktadır.H.Bu makrolar, uygulama dönemlerinde doğrudan ole API ile veya herhangi bir nedenle genellikle gerekiyorsa, Unicode ve mbcs arasında dönüştürmek çok kullanışlıdır.

Genel Bakış

Özel bir dll mfc 3.x'te kullanılan (MFCANS32.dll) arabirimleri ole çağrıldığında Unicode ve mbcs arasında otomatik olarak dönüştürür.Bu dll ole uygulamaları ole API ve arabirimler mbcs, yokmuş gibi her zaman Unicode oldukları halde yazılmasına izin hemen hemen saydam bir katman olan (Macintosh'ta hariç).Bu katman uygun sırada ve izin verilen uygulamaların hızla Win16 Win32 taşınması (mfc, Microsoft Word, Microsoft Excel ve vba, bazıları yalnızca bu teknoloji kullanılan Microsoft uygulamaları), bazen önemli bir performans vardı isabet.Bu nedenle, mfc 4.x bu dll dosyasını kullanmaz ve bunun yerine doğrudan Unicode ole arabirimleri konuştuğu size bildirilir.Bunu yapmak için mfc ole arabirimi için bir arama yaparken mbcs Unicode'a dönüştürmek gereken ve genellikle ole arabirimi uygularken mbcs için Unicode'dan dönüştürmek gerekiyor.Verimli ve kolay bir şekilde işlemek için makrolar sayısı bu dönüştürmeyi kolaylaştırmak için oluşturulmuştur.

Böyle bir makro oluşturma yapılandırılmasının hurdles bellek ayırma biridir.Dizeleri yerde dönüştürülemez çünkü dönüştürülen sonuçları tutacak yeni bellek tahsis edilebilir.Bu aşağıdakine benzer bir kod ile yapılmış:

// 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;

Bu yaklaşım olarak bir dizi sorun.Ana sorun bir sürü kod yazmak için sınama ve hata ayıklama için olmasıdır.Bir şey basit işlev çağrısı oldu, şimdi çok daha karmaşıktır.Buna ek olarak, var. önemli çalışma yükü böylece.Bellek öbek üzerinde tahsis edilen ve Serbest Dönüştürme bitti her zaman vardır.Son olarak, yukarıdaki kod uygun gerekir #ifdefs (kendisi bu dönüştürme işleminin gerçekleşmesi için gerektirmeyen) Unicode ve Macintosh derlemeleri eklendi.

Gelen kurmak için biz hangi 1) maske arasındaki fark çeşitli platformlar, 2) kullanımı etkili bellek ayırma şeması ve 3) varolan içine eklemek kolay olan kaynak kodu bazı makrolar oluşturmak için çözümdür.Tanımları, bir örneði aþaðýdadýr:

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

Bu makro yerine Yukarıdaki kod ile şey çok basit:

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

Burada dönüştürme gerekli değildir, ancak makrolar kullanarak basit ve etkili ek aramalar vardır.

Her makro uygulaması, öbek yerine yığından bellek ayırmak için _alloca() işlevini kullanır.Yığınından bellek ayrılırken Öbek bellek ayırma daha hızlıdır ve bellek işlevi çıkıldığı zaman boşaltılır.Buna ek olarak, arama makroları kaçının MultiByteToWideChar (veya WideCharToMultiByte) birden fazla saat.Gerekli olandan biraz daha fazla bellek ayırarak yapılır.En çok bir tane dönüştüreceği bir mbc biliyoruz wchar ve her wchar en çok iki mbc bayt sahip olacaktır.Her ancak zaman yeterince biraz daha gerekli ayırarak dönüştürme ikinci çağrı ikinci işlemek için dönüştürme işlevi çağrısı önlenmesini.Yardımcı işlev çağrısı AfxA2Whelper dönüştürme gerçekleştirmek için yapılması gereken bağımsız iter sayısını azaltır (adlı, bu küçük kod farklı sonuçlar MultiByteToWideChar doğrudan).

Sırada depolamak için makroları alanınız için geçici bir süre bunu yapan her işlev, _convert adlı bir yerel değişken kullanan makroları dönüştürme bildirmek gerekli.Bu çağırarak yapılır USES_CONVERSION Yukarıdaki örnekte görüldüğü gibi makro.

Genel dönüştürme makrolar hem ole Özel makroları vardır.Bu iki farklı makro ayarlar aşağıda açıklanmıştır.Tüm makroları AFXPRIV bulunur.H.

Genel dönüştürme makrolar

Genel dönüştürme makroları temel mekanizma oluştururlar.Makro örnek ve uygulama A2W, önceki bölümde gösterildiği gibi "Genel" bir makro olur.Bunun için ole özellikle ilişkili değildir.Genel makroları kümesini aşağıda listelenmiştir:

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

Metin dönüştürme yaparken yanı sıra vardır ayrıca makrolar ve dönüştürme yardımcı işlevlerini TEXTMETRIC, DEVMODE, BSTRve ole dizelerini ayrılmış.Bu makroların bu tartışmanın kapsamı dışındadır – için AFXPRIV başvurun.Bu makrolar hakkında daha fazla bilgi için h.

ole dönüştürme makrolar

Beklediğiniz işlevleri işlemek için özel olarak tasarlanmış ole dönüştürme makroları olestr karakter.ole üstbilgi incelerseniz birçok başvuru görürsünüz lpcolestr ve olechar.Bu türler, ole arabirimleri platformuna özgü olmayan bir şekilde kullanılan karakter türünü belirtmek için kullanılır.olechar eşler char , Win16 ve Macintosh platformları ve wchar Win32 içine.

Sayısını tutmak için #ifdef mfc gönde bir minimum kod her dönüştürme için benzer bir makro bölümlerimiz, ole dizeleri söz konusu burada.En sık kullanılan aşağıdaki makroları:

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

Yeniden yapmak için benzer makroları vardır TEXTMETRIC, DEVMODE, BSTRve ole dizelerini ayrılmış.İçin AFXPRIV başvurun.Daha fazla bilgi için h.

Diğer noktalar

Makrolar, sıkı bir döngüde kullanmayın.Örneğin, şu tür bir kod yazmak istemiyor:

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

Yukarıdaki kod ne içeriğini dize bağlı yığın belleğin megabayt ayrılıyor neden lpsz olur!Ayrıca, her döngü tekrarında dize dönüştürmek için zaman alır.Bunun yerine, sabit gibi dönüştürmeleri döngünün dışına taşıyın:

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

Dize sabit ise, sonra içine bir işlev yöntem çağrısı şifreleyebilir.Bu, her seferinde serbest dönüştürme arabelleği izin verir.Örne?in:

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]);
}

Dönüş değeri, return önce verilerin bir kopyasını yapmak anlamına gelir sürece asla makrolar, sonuç.Örneğin, bu kod kötü:

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

Yukarıdaki kod değeri kopyalar şeyler için dönüş değerini değiştirerek sabit:

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

Makroların kullanımı kolay ve hızlı kodunuza eklemek, ancak yukarıdaki uyarılar söyleyebilir gibi bunları kullanırken dikkatli olmanız gerekir.

Ayrıca bkz.

Diğer Kaynaklar

Teknik notlar numarasına göre

Kategoriye göre teknik notlar