TN059: Usando macros de conversão do MFC MBCS/Unicode
Observação: |
---|
A seguinte nota técnica não foi atualizada desde que foi incluída pela primeira vez na documentação online.sistema autônomo resultado, alguns procedimentos e tópicos podem estar desatualizado ou incorreto.Para obter as informações mais recentes, é recomendável que você procura o t ÓPICO de interesse no índice de documentação online. |
Esta nota descreve como usar as macros para conversão Unicode/MBCS, que são definidos no AFXPRIV.H.Essas macros são mais úteis se os negócios de aplicativos diretamente com a API OLE ou por alguma razão, geralmente precisa converter entre Unicode e MBCS.
Visão Geral
No MFC 3.x, foi usada uma DLL especial (MFCANS32.DLL) para converter automaticamente entre Unicode e MBCS quando eram chamados de interfaces OLE.Essa DLL foi uma camada quase transparente OLE aplicativos a serem gravados sistema autônomo se sistema autônomo interfaces e OLE APIs foram MBCS, mesmo que elas sejam sempre Unicode permitidos (exceto no Macintosh).Enquanto essa camada estava conveniente e permitidos aplicativos rapidamente ser portados do Win16 Win32 (MFC, o Microsoft palavra, o Microsoft Excel e o VBA, são apenas alguns dos aplicativos Microsoft que essa tecnologia usada), que tinha um desempenho significativo às vezes, visitas.Por esse motivo, MFC 4.x não usa essa DLL e, em vez disso, conversa diretamente com as interfaces Unicode OLE.Para fazer isso, MFC precisa converter para Unicode para MBCS ao fazer uma telefonar para uma interface OLE e geralmente precisa converter MBCS de Unicode ao implementar uma interface OLE.Para resolver isso com com facilidade e com eficiência, um número de macros foram criado para facilitar essa conversão.
Um das barreiras de maiores de criar tal um conjunto de macros é a alocação de memória.Porque as seqüências de caracteres não podem ser convertidas no lugar, a nova memória para armazenar os resultados convertidos deve ser alocada.Isso poderia ter sido concluído com o código semelhante ao seguinte:
// 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;
Essa abordagem sistema autônomo um número de problemas.O principal problema é que ele é muito código para escrever, testar e depurar.Algo que era uma telefonar de função simples, agora é muito mais complexa.Além disso, há um tempo de execução significativo sobrecarga na fazê-lo.Memória tem que ser alocado no heap e liberados sempre que uma conversão é feita.Finalmente, o código acima precisaria ter apropriado #ifdefs adicionado para versões Unicode e Macintosh (que não exigem a conversão ocorra).
1) 2) 3) A solução de que nós é criar algumas macros que máscara a diferença entre várias plataformas e uso um esquema de alocação de memória eficiente e fácil de inserir o existente são de código-fonte.Eis um exemplo de uma das definições de:
#define A2W(lpa) (\
((LPCSTR)lpa == NULL) ? NULL : (\
_convert = (strnlen(lpa)+1),\
AfxA2WHelper((LPWSTR) alloca(_convert*2),
lpa, _convert)\
)\
)
Usando esta macro em vez do código acima e as coisas são muito mais simples:
// use it to call OLE here
USES_CONVERSION;
pI->SomeFunctionThatNeedsUnicode(T2OLE(lpszA));
Existem chamadas extras onde conversão é necessária, mas usar as macros é simples e eficiente.
A implementação de cada macro usa a função _alloca() alocar a memória da pilha em vez do heap.Alocação de memória da pilha é muito mais rápida do que a alocação de memória na pilha e a memória é liberada automaticamente quando a função é finalizada.Além disso, as macros evitar chamando MultiByteToWideChar (or WideCharToMultiByte) mais de uma vez.Isso é concluído por alocar um bit mais memória do que é necessário.Sabemos que um MBC converterá no máximo um WCHAR e que cada WCHAR teremos um máximo de dois bytes MBC.Alocando um pouco mais de necessário, mas sempre suficiente para manipular a conversão a segunda telefonar segunda telefonar para a função de conversão é evitada.A telefonar à função auxiliar AfxA2Whelper reduz o número de argumento coloca que devem ser executadas para realizar a conversão (Isso resultados em menor de código, que se chamado MultiByteToWideChar diretamente).
Para fazer as macros para que o espaço para armazenar a um comprimento temporário, é necessário declarar uma variável local denominada _convert faz isso em cada função que usa as macros de conversão.Isso é concluído chamando o USES_CONVERSION macro sistema autônomo visto acima no exemplo.
Existem macros conversão genérico e macros específicas de OLE.Esses dois conjuntos diferentes de macro são discutidos abaixo.Todas as macros residem em AFXPRIV.H.
Macros de conversão genérico
As macros de conversão genérico formam o mecanismo subjacente.O exemplo de macro e a implementação mostrada na seção anterior, A2W, é uma tal macro "genérica".Ele não está relacionado ao OLE especificamente.O conjunto de macros genéricos abaixo:
A2CW (LPCSTR) -> (LPCWSTR)
A2W (LPCSTR) -> (LPWSTR)
W2CA (LPCWSTR) -> (LPCSTR)
W2A (LPCWSTR) -> (LPSTR)
Além de fazer conversões de texto, também existem macros e as funções auxiliares para a conversão de TEXTMETRIC, DEVMODE, BSTRe OLE alocado cadeias de caracteres. Essas macros estão além do escopo desta discussão – consulte AFXPRIV.H para obter mais informações sobre essas macros.
Macros de conversão de OLE
As macros de conversão de OLE foram projetadas especificamente para lidar com funções que esperam OLESTR caracteres.Se você examinar os cabeçalhos OLE, você verá muitas referências a LPCOLESTR and OLECHAR.Esses tipos são usados para referir-se o tipo de caracteres usados em interfaces OLE de uma forma que não é específico para a plataforma.OLECHAR maps to char nas plataformas Win16 e Macintosh e WCHAR no Win32.
Para manter o número de # ifdef diretivas no MFC código mínimo temos uma macro similar para cada conversão que onde cadeias de caracteres OLE estão envolvidas.As seguintes macros são as mais usadas:
T2COLE (LPCTSTR) -> (LPCOLESTR)
T2OLE (LPCTSTR) -> (LPOLESTR)
OLE2CT (LPCOLESTR) -> (LPCTSTR)
OLE2T (LPCOLESTR) -> (LPCSTR)
Novamente, existem macros similares para fazer TEXTMETRIC, DEVMODE, BSTRe OLE alocado cadeias de caracteres. Para obter mais informações, consulte AFXPRIV.H.
Outras Considerações
Não use as macros em um loop apertado.Por exemplo, você não quiser escrever o seguinte tipo de código:
void BadIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
for (int ii = 0; ii < 10000; ii++)
pI->SomeMethod(ii, T2COLE(lpsz));
}
O código acima pode resultar na alocação de megabytes de memória na pilha dependendo do que o Sumário da seqüência de caracteres lpsz é!Ele também leva time para converter a cadeia de caracteres para cada iteração do loop.Em vez disso, mova essas conversões constante do loop:
void MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION;
LPCOLESTR lpszT = T2COLE(lpsz);
for (int ii = 0; ii < 10000; ii++)
pI->SomeMethod(ii, lpszT);
}
Se a seqüência de caracteres não for constante, em seguida, encapsule a telefonar do método em uma função.Isso permitirá que o buffer de conversão para ser liberado cada vez.Por exemplo:
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]);
}
Nunca retornar o resultado de uma das macros, a menos que o valor retornado significa fazer uma cópia dos dados antes do retorno.Por exemplo, este código é ruim:
LPTSTR BadConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI->GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; // bad! returning alloca memory
}
O código acima pode ser corrigido alterando o valor retornado para algo que o valor será copiado:
CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION;
LPOLESTR lpsz = NULL;
pI->GetFileName(&lpsz);
LPTSTR lpszT = OLE2T(lpsz);
CoMemFree(lpsz);
return lpszT; // CString makes copy
}
sistema autônomo macros são fáceis de usar e fácil de inserir no código, mas sistema autônomo você pode dizer sobre sistema autônomo condições acima, você precisa ter cuidado ao usá-los.