Partilhar via


Alterações de marshaling

As seções a seguir fornecem um conjunto selecionado de alterações que você pode criar um assembly de interoperabilidade para resolver alguns problemas específicos com a saída do processo de importação:

  • Matrizes em conformidade com o estilo C

  • In/out Arrays estilo C

  • Matrizes de estilo C multidimensional

  • Diferente de zero-limite SAFEARRAY

  • Preservar assinatura

  • Passar nulo em vez de referência para o tipo de valor

Estas seções não representam todos os casos para edição de um assembly de interoperabilidade.Por exemplo, você também pode edição um assembly de interoperabilidade para aprimorar a sua facilidade de uso.A única maneira de determinar quais personalizações são necessárias é realmente escrever código usando o assembly de interoperabilidade.Para obter instruções sobre a edição de assemblies de interoperabilidade, consulte Como: Edite assemblies de interoperabilidade.

O marshaling é afetado quando o cliente e servidor estão em apartments incompatíveis.Os exemplos a seguir, a maioria das empacotado como parâmetros não é compatível de automação e exige uma das seguintes ações:

  • Confirme se tanto cliente quanto servidor estão apartments compatível (e dessa forma, não há nenhum COM marshaling envolvidos).

  • Registre o proxy e stub gerado de Interface Definition linguagem (IDL).Registrando a biblioteca de tipos não ajuda nesses casos porque grande parte das informações necessárias para marshaling não é propagada de IDL para a biblioteca de tipos.

Matrizes em conformidade com o estilo C

A declaração de IDL a seguir mostra uma matriz de estilo C.

HRESULT ConformantArray([in] int cElems, [in, size_is(cElems)] int 
aConf[]);

sistema autônomo esse tipo não é compatível com automação, informações sobre o dimensionar da matriz, sistema autônomo o link entre o primeiro e o segundo parâmetro, não podem ser expresso na biblioteca de tipos.O Type biblioteca Importer (Tlbimp.exe) importa o segundo parâmetro sistema autônomo uma referência para o inteiro e não sistema autônomo um gerenciado array.Você pode ajustar o parâmetro editando o MSIL.

Pesquisar o MSIL para

method public hidebysig newslot virtual 
instance void  ConformantArray([in] int32 cElems,
[in] int32& aConf) runtime managed internalcall

Substituir por

method public hidebysig newslot virtual 
instance void  ConformantArray([in] int32 cElems,
[in] int32[] marshal([]) aConf) runtime managed internalcall

Para telefonar do código gerenciado

int[] param1 = { 11, 22, 33 };
tstArrays.ConformantArray( 3, param1 );

In/out Arrays estilo C

A seguinte declaração de IDL mostra um in/out estilo C da matriz.

HRESULT InOutArray([in, out] int* pcElems, [in, out, size_is(,*pcElems)] 
int** ppInOut);

Nesse caso, a matriz pode ser redimensionada e o novo dimensionar pode ser passado novamente.sistema autônomo esse tipo não é compatível com automação, informações sobre o dimensionar da matriz, sistema autônomo o link entre o primeiro e o segundo parâmetro, não podem ser expresso na biblioteca de tipos.Tlbimp.exe importa o segundo parâmetro sistema autônomo um IntPtr.Embora você ainda pode telefonar esse método a partir do código gerenciado, para redimensionar a matriz, você deve edição o MSIL e usar métodos do Marshal classe para gerenciar manualmente a alocação e desalocação de memória.

Pesquisar o MSIL para

.method public hidebysig newslot virtual 
instance void  InOutArray([in][out] int32& pcElems,
[in][out] native int ppInOut) runtime managed internalcall

Substituir por

.method public hidebysig newslot virtual 
instance void  InOutArray([in][out] int32& pcElems,
[in][out] native int& ppInOut) runtime managed internalcall

Para telefonar do código gerenciado

int[] inArray = { 11, 22, 33 };
int arraySize = inArray.Length;

IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( typeof( int )) * inArray.Length );
Marshal.Copy( inArray, 0, buffer, inArray.Length );
tstArrays.InOutArray( ref arraySize, ref buffer );
if( arraySize > 0 )
{
int[] arrayRes = new int[ arraySize ];
Marshal.Copy( buffer, arrayRes, 0, arraySize );
Marshal.FreeCoTaskMem( buffer );
}

Matrizes de estilo C multidimensional

A declaração de IDL a seguir mostra uma matriz bidimensional, C-estilo.

HRESULT TwoDimArray([in] int cDim, [in, size_is(cDim)] int aMatrix[][3]);

sistema autônomo esse tipo não é compatível com automação, informações sobre o dimensionar e o número de dimensões da matriz, sistema autônomo o link entre o primeiro e o segundo parâmetro, não podem ser expresso na biblioteca de tipos.Tlbimp.exe importa o segundo parâmetro sistema autônomo um IntPtr tipo e não sistema autônomo uma matriz multidimensional gerenciada.Você pode ajustar o parâmetro editando o MSIL.

Pesquisar o MSIL para

.method public hidebysig newslot virtual 
instance void  TwoDimArray([in] int32 cDim,
[in] native int aMatrix) runtime managed internalcall

Substituir por

.method public hidebysig newslot virtual 
instance void  TwoDimArray([in] int32 cDim,
[in] int32[,] marshal([]) aMatrix) runtime managed internalcall

Para telefonar do código gerenciado

int[,] param = {{ 11, 12, 13 }, { 21, 22, 23 }, { 31, 32, 33 }};
tstArrays.TwoDimArray( 3, param );

Diferente de zero-limite SAFEARRAY

A declaração de IDL a seguir mostra um SAFEARRAY parâmetro.

HRESULT InSArray([in] SAFEARRAY(int) *ppsa);

Considere que este SAFEARRAY é limite diferente de zero.No código gerenciado, tais arrays são representadas pelo System.Array Digite. No entanto, por padrão, o importador converte todos os SAFEARRAY parâmetros para referências a gerenciado arrays.Você tem duas opções para alterar o comportamento padrão:

  • Importar todos sistema autônomo arrays em uma biblioteca de tipos sistema autônomo sistema.array tipos usando Tlbimp.exe com o /sysarray comutador.

  • Importe alguns parâmetros sistema autônomo sistema.array tipos editando manualmente o MSIL do seguinte exemplo mostra.

    Pesquisar o MSIL para

    .method public hidebysig newslot virtual 
    instance void  InSArray([in] int32[]&  marshal( safearray int) ppsa) runtime managed internalcall
    

    Substituir por

    .method public hidebysig newslot virtual 
    instance void  InSArray(class [mscorlib]System.Array& marshal( safearray) ppsa) runtime managed internalcall
    

    Chamar a partir do código gerenciado

    int[] lengthsArray = new int[1] { 3 };   
    int[] boundsArray = new int[1] { -1 };
    Array param2 = Array.CreateInstance( typeof(int), lengthsArray, boundsArray );
    for( int i = param2.GetLowerBound( 0 ); i <= param2.GetUpperBound( 0 ); i++ )
    param2.SetValue( i * 10, i ); 
    sum = tstArrays.InSArray( ref param2 );
    

Preservar assinatura

A declaração de IDL a seguir mostra uma assinatura de método COM.

HRESULT TestPreserveSig2([in] int inParam, [out,retval] int* outParam);

As assinaturas de métodos COM Tlbimp.exe é alterado.Parâmetros marcados com [out, retval] em IDL se tornam valores de retorno de métodos gerenciado.Todos os valores HRESULT que indicam falha são transformados em gerenciado exceções.Às vezes, é necessário preservar a assinatura do método COM original, tais sistema autônomo quando o método retorna um valor diferente de sucesso HRESULTs.A representação gerenciado seguinte mostra um exemplo de uma assinatura que você pode modificar.

gerenciado representação na MSIL

.method public hidebysig newslot virtual 
instance int32 TestPreserveSig2([in] int32 inParam) runtime managed internalcall
{

Substituir por

.method public hidebysig newslot virtual 
instance int32 TestPreserveSig2([in] int32 inParam, [out] int32& outParam) runtime managed internalcall preservesig

Para ver qual HRESULT é retornado

int hr = tst.TestPreserveSig2( -3, out retValue );
Console.WriteLine( "Return value is {0}", retValue );
if( hr == 0 )
Console.WriteLine( "HRESULT = S_OK" );
else if ( hr == 1 )
Console.WriteLine( "HRESULT = S_FALSE" );
else
Console.WriteLine( "HRESULT = {0}", hr );

Passar nulo em vez de uma referência a um tipo de valor

A declaração de IDL a seguir mostra um ponteiro IDL para uma estrutura.

HRESULT TestPassingNull([in, unique] Point* refParam);

Tlbimp.exe importa o parâmetro sistema autônomo uma referência para o tipo de valor de Point. Em translation from VPE for Csharp e Visual Basic 2005, um valor nulo de referência ()Nada no Visual Basic) não pode ser passado sistema autônomo um parâmetro quando uma referência a um tipo de valor esperada.Se a função COM requer um valor nulo (Nada) parâmetro, você pode alterar a assinatura, editando o MSIL.

Pesquisar o MSIL para

.method public hidebysig newslot virtual 
instance void  TestPassingNull(
[in] valuetype MiscSrv.tagPoint& refParam) 
runtime managed internalcall

Substituir por

.method public hidebysig newslot virtual 
instance void  TestPassingNull([in] native int) runtime managed internalcall

Assinatura alterada permite que você passe um valor nulo.No entanto, quando você precisar passar alguns valores reais, você deve usar sistema autônomo métodos do realizar realizar marshaling classe, sistema autônomo o exemplo a seguir mostra.

tagPoint p = new tagPoint();
p.x = 3;
p.y = 9;

IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( p ));
Marshal.StructureToPtr( p, buffer, false );
tst.TestPassingNull( buffer );
Marshal.FreeCoTaskMem( buffer );
tst.TestPassingNull( IntPtr.Zero );

Consulte também

Tarefas

Como: edição assemblies de interoperabilidade

Como: Criar wrappers manualmente

Conceitos

Personalizando o tempo de execução Callable Wrappers

Tipos de dados COM

Personalizando COM Callable Wrappers

Referência

Tipo Biblioteca Importer (Tlbimp.exe)