Partilhar via


Padrão de marshaling de matrizes

Em um aplicativo que consiste inteiramente em código gerenciado, o common linguagem tempo de execução passa sistema autônomo in/out parâmetros de tipos de matriz.Por outro lado, o interop marshaler passa uma matriz sistema autônomo in parâmetros por padrão.

Com otimização de fixação, uma matriz blittable pode aparecer para operar sistema autônomo um parâmetro de entrada/saída ao interagir com objetos no apartment mesmo.No entanto, se mais tarde exportar o código para uma biblioteca de tipos usada para gerar o proxy entre máquinas, e essa biblioteca é usada para realizar realizar marshaling as chamadas entre apartments, as chamadas poderá reverter para true no comportamento de parâmetro.

Arrays são complexas por natureza e distinções entre arrays gerenciado e garantem maior de informações que outros tipos blittable não.Este tópico fornece as seguintes informações sobre marshaling de matrizes:

  • Arrays gerenciado

  • Arrays não-gerenciados

  • Passando parâmetros de matriz para código .NET

  • Matrizes de passagem para com.

Arrays gerenciado

Tipos de array gerenciado podem variar; no entanto, a System.Array classe é a base de todos os tipos de matriz. The sistema.array classe possui propriedades para determinar a classificar, comprimento e inferior e limites superiores de uma matriz, bem sistema autônomo métodos para acessar, classificar, pesquisa, copiando e criação de matrizes.

Esses tipos de matriz são dinâmicos e não tem um tipo estático correspondente definido na biblioteca de classes base.É conveniente considerar cada combinação de tipo de elemento e classificar sistema autônomo um tipo distinto de matriz.Portanto, uma matriz unidimensional de inteiros é de um tipo diferente de uma matriz unidimensional tipos dupla.Da mesma forma, uma matriz bidimensional de números inteiros é diferente de uma matriz unidimensional de inteiros.Limites da matriz não são considerados durante a comparação de tipos.

sistema autônomo mostra a tabela a seguir, qualquer instância de um gerenciado matriz deve ser um tipo de elemento específico, classificar e limite inferior.

Tipo de array gerenciado

Tipo de elemento

classificar

Limite inferior

Notação de assinatura

ELEMENT_TYPE_ARRAY

Especificadas pelo tipo.

Especificado por classificar.

Opcionalmente, especificado por limites.

type[n,m]

ELEMENT_TYPE_CLASS

Desconhecido

Desconhecido

Desconhecido

System.Array

ELEMENT_TYPE_SZARRAY

Especificadas pelo tipo.

1

0

type[n]

Arrays não-gerenciados

Arrays não-gerenciados são matrizes seguras COM estilo ou conjuntos de estilo C com comprimento fixo ou variável.Matrizes seguras são autodescritivos arrays que executam o tipo, classificar e limites de dados array associado.Estilo C matrizes são matrizes unidimensionais de tipos com um limite inferior fixo de 0.O serviço de marshaling tem suporte limitado para ambos os tipos de arrays.

Passando parâmetros de matriz para código .NET

sistema autônomo arrays do estilo C e matrizes seguras possam ser transferidas ao código .NET de código não gerenciado sistema autônomo uma matriz segura ou uma matriz de estilo C.A tabela a seguir mostra o valor de tipo não gerenciado e o tipo importado.

Tipo não gerenciado

Tipo importado

() SafeArrayType)

ELEMENT_TYPE_SZARRAY <ConvertedType>

classificar = 1, o limite inferior = 0.dimensionar é conhecido somente se fornecida no gerenciado assinatura.Matrizes seguras não são classificar = 1 ou o limite inferior = 0 não pode ser empacotado sistema autônomo SZARRAY.

Tipo []

ELEMENT_TYPE_SZARRAY <ConvertedType>

classificar = 1, o limite inferior = 0.dimensionar é conhecido somente se fornecida no gerenciado assinatura.

Matrizes seguras

Quando uma matriz segura é importada de uma biblioteca de tipos em um assembly .NET, o array é convertido em uma matriz unidimensional de um tipo conhecido (por exemplo, int).A mesma conversão de tipo de regras que aplicar parâmetros também aplicar a elementos da matriz.Por exemplo, uma matriz segura de BSTR tipos se torna um gerenciado matriz de seqüências de caracteres e uma matriz segura de variantes se torna um gerenciado matriz de objetos.The SAFEARRAY tipo de elemento é capturado de biblioteca de tipos e salvo no SAFEARRAY valor de de oUnmanagedType enumeração.

Como o classificar e limites da matriz segura não podem ser determinados de biblioteca de tipos, a classificar será considerada igual 1 e o limite inferior será considerado 0 igual.O classificar e limites devem ser definidos na gerenciado assinatura produzido pelo Tipo biblioteca Importer (Tlbimp.exe).Se a classificar passada para o método em time de execução difere um SafeArrayRankMismatchException é lançada. Se o tipo da matriz passada em time de execução difere um SafeArrayTypeMismatchException é lançada. O exemplo a seguir mostra as matrizes seguras no código gerenciado e não gerenciado.

Assinatura não gerenciada

HRESULT New1([in] SAFEARRAY( int ) ar);
HRESULT New2([in] SAFEARRAY( DATE ) ar);
HRESULT New3([in, out] SAFEARRAY( BSTR ) *ar);

Assinatura gerenciada

Sub New1(<MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_I4)> _
   ar() As Integer)
Sub New2(<MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_DATE)> _ 
   ar() As DateTime)
Sub New3(ByRef <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VT_BSTR)> _ 
   ar() As String)
void New1([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_I4)] int[] ar) ;
void New2([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_DATE)] 
   DateTime[] ar);
void New3([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VT_BSTR)] 
   ref String[] ar);

Matrizes multidimensionais ou diferente de zero vinculados seguras, pode ser empacotado em código gerenciado, se a assinatura do método produzida pelo Tlbimp.exe é modificada para indicar um tipo de elemento de ELEMENT_TYPE_ARRAY em vez de ELEMENT_TYPE_SZARRAY.sistema autônomo alternativa, você pode usar o /sysarray comutador com o Tlbimp.exe para importar todos sistema autônomo arrays sistema autônomo System.Array objetos. Em casos onde o array que está sendo passado é conhecido deve ser multidimensional, você pode edição o Microsoft intermediate linguagem (MSIL) código produzido pelo Tlbimp.exe e recompilá-lo.Para obter detalhes sobre como modificar o código MSIL, consulte Personalizando o tempo de execução Callable Wrappers.

Matrizes de estilo C

Quando uma matriz de estilo C é importada de uma biblioteca de tipos em um assembly .NET, o array é convertido para ELEMENT_TYPE_SZARRAY.

O tipo de elemento de matriz é determinado a partir da biblioteca de tipos e preservado durante a importação.As mesmas regras de conversão que se aplicam aos parâmetros também se aplicam a elementos da matriz.Por exemplo, uma matriz de LPStr tipos se torna uma matriz de Seqüência de caracteres tipos.Tlbimp.exe captura o tipo de elemento de matriz e aplica o MarshalAsAttribute o atributo do parâmetro.

A classificar de matriz será considerada igual a 1.Se a classificar for maior que 1, a matriz é empacotada sistema autônomo uma matriz unidimensional na ordem da coluna principal.O limite inferior é sempre igual a 0.

Bibliotecas de tipos podem conter matrizes de comprimento fixo ou variável.Tlbimp.exe pode importar matrizes de comprimento apenas fixo de bibliotecas de tipos porque as bibliotecas de tipos não contêm as informações necessárias para realizar realizar marshaling matrizes de comprimento variável.Com matrizes de comprimento fixo, o dimensionar é importado da biblioteca de tipos e capturado no MarshalAsAttribute aplicada ao parâmetro.

Você deve definir manualmente bibliotecas de tipos que contêm matrizes de comprimento variável, conforme mostrado no exemplo a seguir.

Assinatura não gerenciada

HRESULT New1(int ar[10]);
HRESULT New2(double ar[10][20]);
HRESULT New3(LPWStr ar[10]);

Assinatura gerenciada

Sub New1(<MarshalAs(UnmanagedType.LPArray, SizeConst=10)> _
   ar() As Integer)
Sub New2(<MarshalAs(UnmanagedType.LPArray, SizeConst=200)> _
   ar() As Double)
Sub New2(<MarshalAs(UnmanagedType.LPArray, _
   ArraySubType=UnmanagedType.LPWStr, SizeConst=10)> _
   ar() As String)
void New1([MarshalAs(UnmanagedType.LPArray, SizeConst=10)] int[] ar);
void New2([MarshalAs(UnmanagedType.LPArray, SizeConst=200)] double[] ar);
void New2([MarshalAs(UnmanagedType.LPArray, 
   ArraySubType=UnmanagedType.LPWStr, SizeConst=10)] String[] ar);

Embora seja possível aplicar o size_is or length_is atributos a uma matriz na fonte de Interface Definition linguagem (IDL) para transmitir o dimensionar para um cliente, o compilador MIDL (Microsoft Interface Definition linguagem) não se propaga essas informações para a biblioteca de tipos.Sem saber o dimensionar, o realizar marshaling de interoperabilidade serviço não é possível realizar realizar marshaling os elementos da matriz.Conseqüentemente, matrizes de comprimento variável são importadas sistema autônomo argumentos de referência.Por exemplo:

Assinatura não gerenciada

HRESULT New1(int ar[]);
HRESULT New2(int ArSize, [size_is(ArSize)] double ar[]);
HRESULT New3(int ElemCnt, [length_is(ElemCnt)] LPStr ar[]);

Assinatura gerenciada

Sub New1(ByRef ar As Integer)
Sub New2(ByRef ar As Double)
Sub New3(ByRef ar As String)
void New1(ref int ar);  
void New2(ref double ar);  
void New3(ref String ar); 

Você pode fornecer o empacotador com o dimensionar da matriz editando o Microsoft intermediate linguagem (MSIL) código produzido pelo Tlbimp.exe e, em seguida, a recompilação.Para obter detalhes sobre como modificar o código MSIL, consulte Personalizando o tempo de execução Callable Wrappers.Para indicar o número de elementos da matriz, aplicar o MarshalAsAttribute para o parâmetro de matriz da definição do método gerenciado em uma das maneiras a seguintes:

  • Identifique o outro parâmetro que contém o número de elementos na matriz.sistema autônomo parâmetros são identificados por posição, iniciando com o primeiro parâmetro, sistema autônomo número 0.A matriz a ser controlada não pode ser passada sistema autônomo ref ou out parâmetros.Da mesma forma, o parâmetro que contém o dimensionar da matriz deve ser passado por valor (o campo SizeParamIndex não é possível consulte parâmetro out ou ref).[Visual Basic]

    Sub [New](ElemCnt As Integer, _
       <MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
       ar() As Integer)
    
    void New(
       int ElemCnt, 
       [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] int[] ar );
    
  • Defina o dimensionar da matriz sistema autônomo uma constante.Por exemplo:

    Sub [New](<MarshalAs(UnmanagedType.LPArray, SizeConst:=128)> _
       ar() As Integer)
    
    void New(
       [MarshalAs(UnmanagedType.LPArray, SizeConst=128)] int[] ar );
    

Quando se faz o marshaling de arrays a partir de código não gerenciado para código gerenciado, o empacotador verifica o MarshalAsAttribute associado com o parâmetro para determinar o dimensionar da matriz.Se o dimensionar da matriz não for especificado, somente um elemento é empacotado.

Observação:

O MarshalAsAttribute não tem efeito no marshaling de arrays gerenciados para código não gerenciado.Nessa direção, o dimensionar da matriz é determinado pelo exame.Não é possível realizar realizar marshaling um subconjunto de um gerenciado array.

Interop marshaler usa o CoTaskMemAlloc and CoTaskMemFree métodos para alocar e recuperar memória.Alocação de memória executada pelo código não gerenciado também deve usar esses métodos.

Matrizes de passagem para com.

Todos os tipos de array gerenciado podem ser passados para o código não gerenciado do código gerenciado.Dependendo do tipo gerenciado e sistema autônomo atributos aplicados a ele, a matriz pode ser acessada sistema autônomo uma matriz segura ou uma matriz de estilo C, conforme mostrado na tabela seguinte.

Tipo de array gerenciado

Exportadas sistema autônomo

ELEMENT_TYPE_SZARRAY <type>

UnmanagedType() .SafeArraytype)

UnmanagedType.LPArray

Tipo é fornecido na assinatura.classificar é sempre 1, o limite inferior é sempre 0.dimensionar sempre é conhecido em time de execução.

ELEMENT_TYPE_ARRAY <type> <rank>[<bounds>]

() UnmanagedType.SafeArraytype)

UnmanagedType.LPArray

Tipo, classificar, limites são fornecidos a assinatura.dimensionar sempre é conhecido em time de execução.

ELEMENT_TYPE_CLASS <System.Array>

UT_Interface

() UnmanagedType.SafeArraytype)

Tipo, classificar, limites e dimensionar são sempre conhecidas em time de execução.

Há uma limitação na automatização OLE relativas a matrizes de estruturas que contêm LPSTR ou LPWSTR.Portanto, Seqüência de caracteres campos precisam ser empacotado sistema autônomo UnmanagedType.BSTR.Caso contrário, uma exceção será lançada.

ELEMENT_TYPE_SZARRAY

Quando um método que contém um ELEMENT_TYPE_SZARRAY parâmetro (matriz unidimensional) exportado de um assembly .NET para uma biblioteca de tipos, o parâmetro array é convertido para um SAFEARRAY de um determinado tipo.As mesmas regras de conversão aplicam-se aos tipos de elemento de matriz.O Sumário do array gerenciado é copiado da memória gerenciada automaticamente para o SAFEARRAY.Por exemplo:

Assinatura gerenciada

Sub [New](ar() As Long)
Sub [New](ar() As String)
void New(long[] ar );
void New(String[] ar );

Assinatura não gerenciada

HRESULT New([in] SAFEARRAY( long ) ar); 
HRESULT New([in] SAFEARRAY( BSTR ) ar);

A classificar de matrizes seguras é sempre 1 e o limite inferior é sempre 0.O dimensionar é determinado em time de execução pelo dimensionar da matriz gerenciado que está sendo passado.

A matriz também pode ser empacotada sistema autônomo uma matriz de estilo C, usando o MarshalAsAttribute atributo. Por exemplo:

Assinatura gerenciada

Sub [New](<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
   ar() As Long, size as Integer )
Sub [New](<MarshalAs(UnmanagedType.LPArray, SizeParamIndex:=1)> _
   ar() As String, size as Integer )
Sub [New](<MarshalAs(UnmanagedType.LPArray, _
   ArraySubType= UnmanagedType.LPStr, SizeParamIndex:=1)> _
   ar() As String, size as Integer )
void New([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] 
   long [] ar, int size );
void New([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] 
   String [] ar, int size );
void New([MarshalAs(UnmanagedType.LPArray, ArraySubType= 
   UnmanagedType.LPStr, SizeParamIndex=1)] 
   String [] ar, int size );

Assinatura não gerenciada

HRESULT New(long ar[]); 
HRESULT New(BSTR ar[]); 
HRESULT New(LPStr ar[]);

Embora o empacotador tenha sistema autônomo informações de comprimento necessárias para realizar realizar marshaling o array, o comprimento da matriz geralmente é passado sistema autônomo um argumento separado para transmitir o comprimento do computador chamado.

ELEMENT_TYPE_ARRAY

Quando um método que contém um ELEMENT_TYPE_ARRAY parâmetro é exportado de um assembly .NET para uma biblioteca de tipos, o parâmetro array é convertido para um SAFEARRAY de um determinado tipo.O Sumário do array gerenciado é copiado da memória gerenciada automaticamente para o SAFEARRAY.Por exemplo:

Assinatura gerenciada

Sub [New]( ar(,) As Long )
Sub [New]( ar(,) As String )
void New( long [,] ar );
void New( String [,] ar );

Assinatura não gerenciada

HRESULT New([in] SAFEARRAY( long ) ar); 
HRESULT New([in] SAFEARRAY( BSTR ) ar);

A posição, dimensionar e limites de matrizes seguras são determinados em time de execução pelas características de matriz gerenciada.

A matriz também pode ser empacotada sistema autônomo uma matriz de estilo C, aplicando o MarshalAsAttribute atributo. Por exemplo:

Assinatura gerenciada

Sub [New]( <MarshalAs(UnmanagedType.LPARRAY, SizeParamIndex:=1)> _
   ar(,) As Long, size As Integer)
Sub [New]( <MarshalAs(UnmanagedType.LPARRAY, _
   ArraySubType:=UnmanagedType.LPStr, SizeParamIndex:=1)> _
   ar(,) As String, size As Integer)
void New([MarshalAs(UnmanagedType.LPARRAY, SizeParamIndex=1)] 
   long [,] ar, int size );
void New([MarshalAs(UnmanagedType.LPARRAY, 
   ArraySubType= UnmanagedType.LPStr, SizeParamIndex=1)] 
   String [,] ar, int size );

Assinatura não gerenciada

HRESULT New(long ar[]); 
HRESULT New(LPStr ar[]);

Não não possível empacotar matrizes aninhadas.Por exemplo, a assinatura a seguir gera um erro quando exportados com o Tipo biblioteca Exporter (Tlbexp.exe).

Assinatura gerenciada

Sub [New]( ar()()() As Long )
void New(long [][][] ar );

ELEMENT_TYPE_CLASS <sistema.Array>

Quando um método que contém um System.Array parâmetro é exportado de um assembly .NET para uma biblioteca de tipos, o parâmetro array é convertido para um _Array interface.O Sumário do gerenciado matriz são acessíveis somente através dos métodos e propriedades do _Array interface.sistema.array também pode ser empacotado sistema autônomo um SAFEARRAY usando o MarshalAsAttribute atributo. Quando empacotado sistema autônomo uma matriz segura, sistema autônomo elementos da matriz são empacotados sistema autônomo variantes.Por exemplo:

Assinatura gerenciada

Sub New1( ar As System.Array )
Sub New2( <MarshalAs(UnmanagedType.Safe array)> ar As System.Array )
void New1( System.Array ar );
void New2( [MarshalAs(UnmanagedType.Safe array)] System.Array ar );

Assinatura não gerenciada

HRESULT New([in] _Array *ar); 
HRESULT New([in] SAFEARRAY(VARIANT) ar);

Matrizes em estruturas

Estruturas não gerenciadas podem conter conjuntos incorporados.Por padrão, esses campos de matriz incorporada são empacotados sistema autônomo um SAFEARRAY.No exemplo a seguir, s1 é uma matriz incorporada é alocada diretamente dentro da estrutura de si mesmo.

Representação não gerenciada

struct MyStruct {
    short s1[128];
}

Arrays podem ser empacotadas sistema autônomo UnmanagedType.ByValArray, que requer a conjunto o MarshalAsAttribute.SizeConst campo.O dimensionar pode ser definido apenas sistema autônomo uma constante.O código a seguir mostra a definição correspondente gerenciada de MyStruct.

Public Structure <StructLayout(LayoutKind.Sequential)> MyStruct
   Public <MarshalAs(UnmanagedType.ByValArray, SizeConst := 128)> _
     s1() As Short
End Structure
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct {
   [MarshalAs(UnmanagedType.ByValArray, SizeConst=128)] public short[] s1;
}

Consulte também

Conceitos

Blittable e tipos Blittable não

Atributos direcionais

Copiando e fixação

Outros recursos

Comportamento de marshaling padrão