Exemplo de estruturas

Este exemplo demonstra como passar uma estrutura que aponta para uma segunda estrutura, passe uma estrutura com uma estrutura incorporada e passar uma estrutura com uma matriz incorporada.

O código-fonte para os exemplos de código a seguir é fornecido pelo.NET estrutura Invocação de plataforma Tecnologia Exemplo.

O exemplo de estruturas utiliza as seguintes funções não gerenciadas, mostradas com sua declaração de função original:

  • TestStructInStruct exportados de PinvokeLib.dll.

    int TestStructInStruct(MYPERSON2* pPerson2);
    
  • TestStructInStruct3 exportados de PinvokeLib.dll.

    void TestStructInStruct3(MYPERSON3 person3);
    
  • TestArrayInStruct exportados de PinvokeLib.dll.

    void TestArrayInStruct( MYARRAYSTRUCT* pStruct );
    

PinvokeLib.dll é uma biblioteca de não gerenciada personalizada que contém implementações de quatro estruturas e funções listadas anteriormente: MYPERSON, MYPERSON2, MYPERSON3, and MYARRAYSTRUCT.Essas estruturas de contenham os seguintes elementos:

typedef struct _MYPERSON
{
   char* first; 
   char* last; 
} MYPERSON, *LP_MYPERSON;

typedef struct _MYPERSON2
{
   MYPERSON* person;
   int age; 
} MYPERSON2, *LP_MYPERSON2;

typedef struct _MYPERSON3
{
   MYPERSON person;
   int age; 
} MYPERSON3;

typedef struct _MYARRAYSTRUCT
{
   bool flag;
   int vals[ 3 ]; 
} MYARRAYSTRUCT;

O gerenciadoMyPerson, MyPerson2, MyPerson3, e MyArrayStruct estruturas têm a característica do seguinte:

  • MyPerson contém somente os membros da seqüência de caracteres. The Conjunto de caracteres campo define as seqüências de caracteres de formato ANSI quando transmitido para a função não gerenciada.

  • MyPerson2 contém um IntPtr to the MyPerson estrutura. The IntPtr tipo substitui o ponteiro original para a estrutura não gerenciada como aplicativos do .NET Framework não usam ponteiros, a menos que o código está marcado como não seguro.

  • MyPerson3 contém MyPerson sistema autônomo uma estrutura incorporada. Uma estrutura incorporada em outra estrutura pode ser achatada colocando sistema autônomo elementos da estrutura incorporado diretamente para a estrutura principal ou deixá-lo sistema autônomo uma estrutura incorporada, sistema autônomo é concluído neste exemplo.

  • MyArrayStruct contém uma matriz de inteiros. The MarshalAsAttribute Define o atributo de UnmanagedType valor de enumeração para ByValArray, que é usado para indicar o número de elementos na matriz.

Para todas as estruturas neste exemplo, a StructLayoutAttribute o atributo é aplicado a garantir que os membros são organizados em memória seqüencialmente, na ordem em que aparecem.

The LibWrap classe contém protótipos gerenciado para o TestStructInStruct, TestStructInStruct3, e TestArrayInStruct os métodos chamados App classe. Cada protótipo declara um único parâmetro, da seguinte maneira:

  • TestStructInStruct declara uma referência ao tipo MyPerson2 sistema autônomo seu parâmetro.

  • TestStructInStruct3 declara tipo MyPerson3 sistema autônomo seu parâmetro e passa o parâmetro por valor.

  • TestArrayInStruct declara uma referência ao tipo MyArrayStruct sistema autônomo seu parâmetro.

Estruturas sistema autônomo argumentos para métodos são passadas por valor, a menos que o parâmetro contém o ref (ByRefpalavra-chave no Visual Basic).Por exemplo, a TestStructInStruct método passa uma referência (o valor de um endereço) para um objeto do tipo MyPerson2 para código não gerenciado. Para manipular a estrutura que MyPerson2 pontos, o exemplo cria um buffer de dimensionar especificado e retorna seu endereço combinando o Marshal.AllocCoTaskMem e Marshal.SizeOf métodos. Em seguida, o exemplo copia o conteúdo da estrutura gerenciada para o buffer não-gerenciado.Finalmente, o exemplo usa o Marshal.PtrToStructure método para realizar realizar marshaling dados do buffer não-gerenciado em um objeto gerenciado e o Marshal.FreeCoTaskMem método para liberar o bloco não gerenciado de memória.

Declaração de protótipos

' Declares a managed structure for each unmanaged structure.
< StructLayout( LayoutKind.Sequential, CharSet := CharSet.Ansi )> _
Public Structure MyPerson
   Public first As String
   Public last As String
End Structure 'MyPerson

< StructLayout( LayoutKind.Sequential )> _
Public Structure MyPerson2
   Public person As IntPtr
   Public age As Integer
End Structure 'MyPerson2

< StructLayout( LayoutKind.Sequential )> _
Public Structure MyPerson3
   Public person As MyPerson
   Public age As Integer
End Structure 'MyPerson3

< StructLayout( LayoutKind.Sequential )> _
Public Structure MyArrayStruct 
   Public flag As Boolean
   < MarshalAs( UnmanagedType.ByValArray, SizeConst:=3 )> _
   Public vals As Integer()
End Structure 'MyArrayStruct

Public Class LibWrap
   ' Declares managed prototypes for unmanaged functions.
   Declare Function TestStructInStruct Lib "..\LIB\PinvokeLib.dll" ( _
      ByRef person2 As MyPerson2 ) As Integer
   Declare Function TestStructInStruct3 Lib "..\LIB\PinvokeLib.dll" ( _
      ByVal person3 As MyPerson3 ) As Integer
   Declare Function TestArrayInStruct Lib "..\LIB\PinvokeLib.dll" ( _
      ByRef myStruct As MyArrayStruct ) As Integer   
End Class 'LibWrap
// Declares a managed structure for each unmanaged structure.
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct MyPerson 
{
   public String first; 
   public String last;
}
[ StructLayout( LayoutKind.Sequential )]
public struct MyPerson2 
{
   public IntPtr person;
   public int age;
}
[ StructLayout( LayoutKind.Sequential )]
public struct MyPerson3 
{
   public MyPerson person;
   public int age;
}
[ StructLayout( LayoutKind.Sequential )]
public struct MyArrayStruct 
{
   public bool flag;
   [ MarshalAs( UnmanagedType.ByValArray, SizeConst=3 )] 
   public int[] vals;
}

public class LibWrap
{
   // Declares a managed prototype for unmanaged function.
   [ DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern int TestStructInStruct( ref MyPerson2 person2 );
   [ DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern int TestStructInStruct3( MyPerson3 person3 );
   [ DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern int TestArrayInStruct( ref MyArrayStruct 
   myStruct );
}

Chamando funções

Public Class App
   Public Shared Sub Main()
      ' Structure with a pointer to another structure. 
      Dim personName As MyPerson
      personName.first = "Mark"
      personName.last = "Lee"
      
      Dim personAll As MyPerson2
      personAll.age = 30
      
      Dim buffer As IntPtr = Marshal.AllocCoTaskMem( Marshal.SizeOf( _
      personName ))
      Marshal.StructureToPtr( personName, buffer, False )
      
      personAll.person = buffer
      
      Console.WriteLine( ControlChars.CrLf & "Person before call:" )
      Console.WriteLine( "first = {0}, last = {1}, age = {2}", _
      personName.first, personName.last, personAll.age )
      
      Dim res As Integer = LibWrap.TestStructInStruct( personAll )
      
      Dim personRes As MyPerson = _
         CType( Marshal.PtrToStructure( personAll.person, _
         GetType( MyPerson )), MyPerson )
      
      Marshal.FreeCoTaskMem( buffer )
      
      Console.WriteLine( "Person after call:" )
      Console.WriteLine( "first = {0}, last = {1}, age = {2}", _
      personRes.first, _
         personRes.last, personAll.age )
      
      ' Structure with an embedded structure.
      Dim person3 As New MyPerson3()
      person3.person.first = "John"
      person3.person.last = "Evens"
      person3.age = 27
      LibWrap.TestStructInStruct3( person3 )
      
      ' Structure with an embedded array.
      Dim myStruct As New MyArrayStruct()
      
      myStruct.flag = False
      Dim array( 2 ) As Integer
      myStruct.vals = array
      myStruct.vals( 0 ) = 1
      myStruct.vals( 1 ) = 4
      myStruct.vals( 2 ) = 9
      
      Console.WriteLine( ControlChars.CrLf & "Structure with array _
      before call:" )
      Console.WriteLine( myStruct.flag )
      Console.WriteLine( "{0} {1} {2}", myStruct.vals( 0 ), _
         myStruct.vals( 1 ), myStruct.vals( 2 ) )
      
      LibWrap.TestArrayInStruct( myStruct )
      Console.WriteLine( ControlChars.CrLf & "Structure with array _
      after call:" )
      Console.WriteLine( myStruct.flag )
      Console.WriteLine( "{0} {1} {2}", myStruct.vals( 0 ), _
         myStruct.vals( 1 ), myStruct.vals( 2 ) )
   End Sub 'Main
End Class 'App
public class App
{
   public static void Main()
   {
      // Structure with a pointer to another structure. 
      MyPerson personName;
      personName.first = "Mark";
      personName.last = "Lee";
      
      MyPerson2 personAll;
      personAll.age = 30;
      
      IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( 
      personName ));
      Marshal.StructureToPtr( personName, buffer, false );
      
      personAll.person = buffer;
      
      Console.WriteLine( "\nPerson before call:" );
      Console.WriteLine( "first = {0}, last = {1}, age = {2}", 
         personName.first, personName.last, personAll.age ); 
      
      int res = LibWrap.TestStructInStruct( ref personAll );
      
      MyPerson personRes = 
         (MyPerson)Marshal.PtrToStructure( personAll.person, 
         typeof( MyPerson ));
      
      Marshal.FreeCoTaskMem( buffer );
      
      Console.WriteLine( "Person after call:" );
      Console.WriteLine( "first = {0}, last = {1}, age = {2}", 
         personRes.first, personRes.last, personAll.age );
      
      // Structure with an embedded structure.
      MyPerson3 person3 = new MyPerson3();
      person3.person.first = "John";
      person3.person.last = "Evens";
      person3.age = 27;
      LibWrap.TestStructInStruct3( person3 );
      
      // Structure with an embedded array.
      MyArrayStruct myStruct = new MyArrayStruct();
      
      myStruct.flag = false;
      myStruct.vals = new int[ 3 ];
      myStruct.vals[ 0 ] = 1;
      myStruct.vals[ 1 ] = 4;
      myStruct.vals[ 2 ] = 9;
      
      Console.WriteLine( "\nStructure with array before call:" );
      Console.WriteLine( myStruct.flag );
      Console.WriteLine( "{0} {1} {2}", myStruct.vals[ 0 ], 
         myStruct.vals[ 1 ], myStruct.vals[ 2 ] );
      
      LibWrap.TestArrayInStruct( ref myStruct );
      Console.WriteLine( "\nStructure with array after call:" );
      Console.WriteLine( myStruct.flag );
      Console.WriteLine( "{0} {1} {2}", myStruct.vals[ 0 ], 
         myStruct.vals[ 1 ], myStruct.vals[ 2 ] );
   }
}

Consulte também

Conceitos

marshaling de classes, estruturas e uniões

Tipos de dados de invocação de plataforma

Criando protótipos em código gerenciado