variedade WCHAR não devidamente marshalled
-
21-08-2019 - |
Pergunta
Eu tenho uma interface COM com uma definição de método seguinte (notação IDL):
SCODE GetText( [in, out] ULONG* pcwcBuffer,
[out, size_is(*pcwcBuffer)] WCHAR* awcBuffer );
Typelib empacotamento é usado para COM +, a biblioteca tipo é registrado, outros métodos do allright trabalho interface quando chamado através de COM +, mas não este método.
As cópias do lado do servidor uma matriz de WCHARs na awcBuffer
e o seu comprimento em pwcBuffer
, sem saturação de buffer nunca ocorre.
static const wchar_t* Text = L"Sample";
STDMETHODIMP CImpl::GetText( ULONG* bufferLength, WCHAR* buffer )
{
const int length = wcslen( Text );
*bufferLength = length;
memcpy( buffer, Text, length * sizeof( WCHAR ) );
return S_OK;
}
Quando o cliente chama esse método através do COM + o conteúdo do buffer se perde. Especificamente apenas o primeiro caractere de largura é preservada - se o servidor copia cadeia de caracteres "exemplo" de largura, o cliente recebe apenas "S" string. O valor de retorno sobre o tamanho do cliente é S_OK, o tamanho do buffer retornado para o cliente é exatamente o mesmo que o servidor copiado.
Eu finalmente mudou para BSTR para resolver este problema, mas é realmente interessante porque toda a construção olhando válida não funciona.
Qual é a possível razão do comportamento descrito?
Solução
IIRC, o marshaller typelib ignora o atributo size_is -. Assim, apenas 1 char é empacotado
Outras dicas
J. Passagem é certo. Para o marshaller typelib para o trabalho, a interface COM deve ser de automação OLE compatíveis. O marshaller typelib é implementado em oleaut32.dll, então eu acho que há uma pista no nome.
[size_is] é perfeitamente válido IDL e compilado em um typelib válido, mas o empacotador typelib só pode lidar com um subconjunto de interfaces válidos. Esse subconjunto é normalmente referido como OLE Automation. Como um aparte, os clientes VB6 só posso falar OLE Automation, para que eles não seriam capazes de consumir a sua interface de qualquer um.
Tente marcar sua interface com o atributo [oleautomation] em sua IDL. Deve dar-lhe uma mensagem de aviso ou de erro que pode apontar-lhe mais informações sobre o assunto.
Em "normal" COM, você poderia gerar a / stub DLL do proxy do seu IDL para fazer a triagem, mas eu tenho medo que eu não me lembro se COM + usaria seu código marshalling personalizado mesmo se deu ao trabalho de construí-lo .
Update: no livro de Juval Lowy "COM e .NET Services Component", achei que esta declaração: " ... componentes configurados não podem usar interfaces que exigem empacotamento personalizado ". Então eu acho que a interface nunca vai funcionar no COM +. Se você puder, re-escrita para usar um BSTR vez.
par de perguntas:
- Por que você não está usando
BSTR
? - Você tem as fontes da função
GetText
? - Qual é o tamanho do buffer retornado pela função?