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
Personalizando COM Callable Wrappers