Pergunta

Eu tenho uma função COM que deve retornar um safearray através de um LPSAFEARRAY* parâmetro out. A função cria o safearray usando o ATL's CComSafeArray classe de modelo. Minha implementação ingênua usa CComSafeArray<T>::Detach() Para mover a propriedade da variável local para o parâmetro de saída:

void foo(LPSAFEARRAY* psa)
{
    CComSafeArray<VARIANT> ret;
    ret.Add(CComVariant(42));
    *psa = ret.Detach();
}

int main()
{
    CComSafeArray<VARIANT> sa;
    foo(sa.GetSafeArrayPtr());

    std::cout << sa[0].lVal << std::endl;
}

O problema é que CComSafeArray::Detach() executa um Unlock operação para que quando o novo proprietário do SafeArray (Main's sa neste caso) é destruído, a fechadura não é zero e Destroy falha em desbloquear o SafeArray com E_UNEXPECTED (Isso leva a um vazamento de memória, pois o SafeArray não é desalocado).

Qual é a maneira correta de transferir a propriedade entre os CCOMSAFearrays através de um limite de método COM?


Editar: Da resposta única até agora, parece que o erro está do lado do cliente (main) e não do lado do servidor (foo), mas acho difícil acreditar que CComSafeArray não foram projetados para este caso de uso trivial, deve haver uma maneira elegante de tirar um Safearray de um método COM em um CComSafeArray.

Foi útil?

Solução

O problema é que você define o recebimento CComSafeArrayO ponteiro interno é diretamente. Use o Attach() método para anexar um existente SAFEARRAY para um CComSafeArray:

LPSAFEARRAY ar;
foo(&ar);
CComSafeArray<VARIANT> sa;
sa.Attach(ar);

Outras dicas

Apenas para confirmar que a resposta marcada é a correta. Os invólucros de Raii não podem trabalhar nos limites da COM.

A implementação do método postada não está correta, você não pode assumir que o chamador fornecerá um SafeArray válido. Just [out] não é um atributo válido na automação, ele deve ser [out, retval] ou [in, out]. Se for [fora, retval], que é assim, o método deve criar uma nova matriz do zero. Se estiver [em, fora], o método deve destruir a matriz passada se não corresponder ao tipo de matriz esperado e criar um novo.

Eu acho que onde não havia intenção de permitir esse caso de uso. Provavelmente não foi o mesmo desenvolvedor que escreveu CComVariant & CComPtr :)

Acredito que CComSafeArrayO autor do autor considerou a semântica do valor como objetivo principal; Anex/desapego pode ser simplesmente um recurso "bônus".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top