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

Bu Not, AFXPRIV içinde tanımlanan mbcs/Unicode dönüşümü için makroları kullanmayı açıklamaktadır.h. Bu makrolar uygulama fırsatlar doğrudan ole API ile ya da nedense genellikle ihtiyacı varsa Unicode ve mbcs arasında dönüştürmek en yararlı.

Genel bakış

Özel bir dll mfc 3.x'te kullanılan (MFCANS32.dll) mbcs arasında Unicode ole arabirimleri çağrıldığında otomatik olarak dönüştürmek için. Bu dll ole uygulamaları ole API'leri ve arabirimleri mbcs, sanki onlar her zaman Unicode olsa bile yazılmasına izin neredeyse şeffaf bir tabaka olarak (hariç Macintosh üzerinde). Bu tabaka uygun süre ve uygulamaları hızla Win16 Win32 için taşıdık için izin (mfc, Microsoft Word, Microsoft Excel ve vba, bazıları sadece bu teknoloji kullanılan Microsoft uygulamaları), Ayrıca bazen önemli bir performans vardı çarptı. Bu nedenle, mfc 4.x bu dll dosyasını kullanmaz ve yerine doğrudan Unicode ole arabirimler için konuşur. Bunu yapmak için mfc ole arabirim çağrısı yaparken mbcs Unicode'a dönüştürmek gerekir ve genellikle mbcs için ole arabirim uygularken Unicode'dan dönüştürmek gerekiyor. Verimli ve kolay bir şekilde ele almak, makrolar sayısı bu dönüştürmeyi kolaylaştırmak için oluşturulan.

Bellek ayırma gibi makro kümesi oluşturma en büyük engeller biridir. Dizeleri yerinde dönüştürülemez çünkü dönüştürülen sonuçları tutmak için yeni bellek tahsis gerekir. Bu kod aşağıdakine benzer yapılmış:

/ / Biz lpszA bir mbcs dize dönüştürmek istediğiniz
int nLen = MultiByteToWideChar (cp_acp, 0, lpszA, -1, null, null);
lpwstr lpszW yeni wchar [nLen]; =
MultiByteToWideChar (cp_acp, 0, lpszA, -1, lpszW, nLen);
/ / ole burada aramak için kullanmak
pI->SomeFunctionThatNeedsUnicode(lpszW);
/ / string ücretsiz
[] lpszW Sil

Bu yaklaşım sorunları sayısı. Asıl sorun, yazmak, sınamak ve hatalarını ayıklamak için kod çok olmasıdır. Bir şey artık çok daha karmaşık, basit fonksiyon çağrısı oldu. Ayrıca, orada önemli bir çalışma yükü bu sayede. Öbek üzerinde ayrılmış ve her zaman bir dönüşüm yapılır serbest hafıza vardır. Son olarak, yukarıdaki kod uygun gerekir #ifdefs için (ki bu dönüşüm gerçekleşmesi gerekmez) Unicode ve Macintosh kurar eklendi.

Biz geldi hangi 1) maske arasındaki fark çeşitli platformlarda, 2) kullanımı etkili bellek ayırma şeması ve 3) mevcut içine eklemek kolay olan kaynak kodu bazı makrolar oluşturmak için çözümdür. İşte örnek olarak tanımlar:

# define A2W(lpa) (\
 nbsp;  ((LPCTSTR) lpa == null)? &NULL: (\
           _convert (strlen (lpa) + 1) = \
        AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert) \
    )\
)

Bu makro Yukarıdaki kod yerine ve şeyler kullanarak çok basit:

/ / ole burada aramak için kullanmak
USES_CONVERSION;
pI->SomeFunctionThatNeedsUnicode(T2OLE(lpszA))

Orada burada dönüştürme gerekli değildir, ancak makrolar kullanarak basit ve etkili ekstra çağrılar.

Her makro uygulaması, öbek yerine yığından bellek ayırmak için _alloca() işlevini kullanır. Yığınından bellek ayırma Öbek bellek ayırma daha hızlıdır ve işlev çıkıldığı zaman bellek otomatik olarak serbest. Ayrıca, MultiByteToWideChar (ya da WideCharToMultiByte) arama makroları önlemek birden çok kez. Bu gerekli olandan biraz daha fazla bellek ayırarak yapılır. Biz bir mbc en bir wchar dönüştürür ve her wchar için biz en çok iki mbc bayt olacak biliyorum. Ama her zaman yeterince biraz fazla gerekli ayırarak ikinci ikinci arama dönüşüm işlemek için dönüştürme işlevini kaçınılır. AfxA2Whelper Yardımcısı işlevi çağrısı (Eğer doğrudan MultiByteToWideChar adı verilen bu küçük kodu, daha sonuç) dönüştürme gerçekleştirmek için yapılması gereken bağımsız iter azaltır.

Sırada depolamak için alan makrolar için geçici bir süre o does bu her işlev, _convert adlı bir yerel değişken kullanır dönüşüm makroları bildirmek gereklidir. Bu yukarıdaki örnekte görüldüğü gibi USES_CONVERSION makro çağırarak yapılır.

Genel dönüştürme makrolar ve ole belirli makrolar vardır. Bu iki farklı makro setleri, aşağıda anlatılmıştır. Tüm makroları AFXPRIV içinde 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 olduğunu. Özellikle ole bir ilişkisi vardır. Genel makroları kümesini aşağıda listelenmiştir:

 A2CW (lpcstr) - gt; (LPCWSTR)
A2W (lpcstr) - > (lpwstr)
W2CA (lpcwstr) - > (LPCTSTR)
W2A (lpcwstr) - > (lpstr)

Metin dönüştürme yaparken, yanında Ayrıca makroları vardır ve TEXTMETRIC, devmode, bstrve ole dönüştürmek yardımcı fonksiyonları dizeleri tahsis edilir. Bu makrolar, bu tartışmanın kapsamı dışındadır-için AFXPRIV bakın.H bu makrolar hakkında daha fazla bilgi.

Ole makroları dönüştürme

Ole dönüşüm makrolar özellikle bekliyoruz olestr karakter fonksiyonları işlemek için tasarlanmıştır. ole üstbilgi incelerseniz birçok başvuruları lpcolestr ve olechargöreceksiniz. Bu türler, ole arabirimleri platforma özgü olmayan bir şekilde kullanılan karakter türünü belirtmek için kullanılır. Char Win16 ve Macintosh platformlarda ve wchar de Win32 olechar maps.

Her bir dönüşüm için benzer bir makro var #ifdef yönerge sayısını mfc kod minimumda tutmak için burada ole dizeleri konusu. Aşağıdaki makroları en sık kullanılan:

T2COLE (lpctstr) - gt; (LPCOLESTR)
T2OLE (lpctstr) - > (lpolestr)
OLE2CT (lpcolestr) - > (lpctstr)
OLE2T (lpcolestr) - > (LPCTSTR)

Yine TEXTMETRICyapmak için benzer makro, devmode, bstrve ole dizelerini ayrılmış. İçin AFXPRIV başvurun.Daha fazla bilgi için h.

Diğer hususlar

Makrolar, sıkı bir döngüde kullanmayın. Örneğin, aşağıdaki tür kodu yazmak istemiyorum:

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

Yukarıdaki kod MB bellek dizesi içeriği&ne bağlı yığında ayrılırken neden olabilir lpsz ise! nbsp; Ayrıca, döngünün her yineleme için dize dönüştürmek için zaman alır. Bunun yerine hareket döngü dışında sürekli bu tür dönüşümleri:

void MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
lpcolestr lpszT = T2COLE(lpsz);
for (int II = 0; II lt; 10000; II ++)
pI - > SomeMethod (II, lpszT);
}

Dize sabit değilse, sonra kapsüllemek için bir işlev yöntemi çağrısı. Bu her zaman Serbest Dönüştürme arabelleği sağlayacaktır. Örneğin:

void CallSomeMethod (int II, lpctstr lpsz)
{
USES_CONVERSION;
pI-gt;SomeMethod (II, T2COLE(lpsz));
}

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

Dönüş değeri veriyi geri önce bir kopyasını yapmak ima sürece hiç bir makro, sonucunu döndürmek. Örneğin, bu kod kötü:

Lptstr BadConvert(ISomeInterface* pI)
{
USES_CONVERSION;
lpolestr lpsz = null;
pI-gt;GetFileName(&lpsz);
lptstr lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; / / bozuk! dönen alloca bellek
}

Yukarıdaki kod değeri kopyalayan bir şey dönüş değeri değiştirerek sabit:

CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION;
lpolestr lpsz = null;
pI-gt;GetFileName(&lpsz);
lptstr lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; / / CString yapar Kopyala
}

Makro kodunuzun eklemek kolay ve basit-e doğru kullanma, ama bunları kullanırken dikkatli olun ihtiyacınız olarak yukarıdaki uyarılar söyleyebilirim,.

Teknik notlar numarasına göre |nbsp; Teknik notlar kategorisine göre

Index