Exemplo de OutArrayOfStructs

Esse exemplo mostra sistema autônomo passar uma matriz de estruturas que contém números inteiros e seqüências de caracteres sem parâmetros para uma função não gerenciada.O código de fonte de exemplo está incluído no Invocação de plataforma Tecnologia Exemplo.

Este exemplo demonstra como chamar uma função nativa usando o Marshal classe e usando código não seguro.

Este exemplo usa funções de wrapper e plataforma invoca definido no PinvokeLib.dll, também é fornecido nos arquivos de fonte. Ele usa o TestOutArrayOfStructs função e o MYSTRSTRUCT2 estrutura. A estrutura contém os seguintes elementos:

typedef struct _MYSTRSTRUCT2
{
   char* buffer;
   UINT size; 
} MYSTRSTRUCT2;

The MyStruct classe contém um objeto de seqüência de caracteres ANSI. The CharSet campo especifica o formato ANSI. MyUnsafeStruct, é uma estrutura que contém um IntPtr Digite em vez de uma seqüência de caracteres.

The LibWrap classe contém o sobrecarregado TestOutArrayOfStructs método de protótipo. Se um método declarar um ponteiro sistema autônomo um parâmetro, a classe deve ser marcada com o unsafe palavra-chave. Porque Visual Basic 2005 não é possível usar o código não seguro, o método sobrecarregado, modificador não seguro e o MyUnsafeStruct estrutura são desnecessários.

The App classe implementa a UsingMarshal método executa todas as tarefas necessárias para passar a matriz. A matriz é marcada com o out (ByRef no Visual Basic) a palavra-chave para indicar que os dados passa do computador chamado ao chamador. A implementação usa a seguinte Marshal métodos da classe:

  • PtrToStructure para realizar realizar marshaling dados de buffer não-gerenciado para um objeto gerenciado.

  • DestroyStructure para versão a memória reservada para seqüências de caracteres na estrutura.

  • FreeCoTaskMem Para liberar a memória reservada para a matriz.

Conforme mencionado anteriormente, translation from VPE for Csharp permite que o código não seguro e Visual Basic 2005 não ocorre. No exemplo translation from VPE for Csharp, UsingUnsafe é uma implementação do método alternativo que usa ponteiros em vez da Marshal classe para passar de volta a matriz que contém o MyUnsafeStruct estrutura.

Declaração de protótipos

' Declares a class member for each structure element.
< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Ansi )> _
Public Class MyStruct 
   Public buffer As String 
   Public someSize As Integer
End Class 'MyStruct

Public Class LibWrap
' Declares a managed prototype for the unmanaged function.
   Declare Sub TestOutArrayOfStructs Lib "..\\LIB\\PinvokeLib.dll" ( _
      ByRef arrSize As Integer, ByRef outArray As IntPtr )
End Class 'LibWrap
// Declares a class member for each structure element.
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public class MyStruct 
{
   public String buffer;
   public int size;
}
// Declares a structure with a pointer.
[ StructLayout( LayoutKind.Sequential )]
public struct MyUnsafeStruct 
{
   public IntPtr buffer;
   public int size;
}

public unsafe class LibWrap
{
   // Declares managed prototypes for the unmanaged function.
   [ DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern void TestOutArrayOfStructs( out int size, 
      out IntPtr outArray );
   [ DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern void TestOutArrayOfStructs( out int size, 
   MyUnsafeStruct** outArray );
}

Chamando funções

Public Class App
   Public Shared Sub Main()
      Console.WriteLine( ControlChars.CrLf & "Using marshal class" & _
ControlChars.CrLf )
      UsingMarshal()
      'Visual Basic 2005 cannot use unsafe code.
   End Sub 'Main
   
   Public Shared Sub UsingMarshal()   
      Dim arrSize As Integer
      Dim outArray As IntPtr
      LibWrap.TestOutArrayOfStructs( arrSize, outArray )
      Dim manArray(arrSize - 1) As MyStruct
      Dim current As IntPtr = outArray
      Dim i As Integer
      
      For i = 0 To arrSize - 1
      
         manArray(i) = New MyStruct()
         Marshal.PtrToStructure( current, manArray(i))
         
         Marshal.DestroyStructure( current, GetType( MyStruct )) 
         current = IntPtr.op_explicit( current.ToInt64() _
           + Marshal.SizeOf( manArray(i) ))
         
         Console.WriteLine( "Element {0}: {1} {2}", i, manArray(i)._
           buffer, manArray(i).someSize )
      Next i
      Marshal.FreeCoTaskMem( outArray )
   End Sub 'UsingMarshal
End Class 'App
public class App
{
   public static void Main()
   {
      Console.WriteLine( "\nUsing marshal class\n" );
      UsingMarshal();
      Console.WriteLine( "\nUsing unsafe code\n" );
      UsingUnsafe();
   }
   
   public static void UsingMarshal()   
   {
      int size;
      IntPtr outArray;
      LibWrap.TestOutArrayOfStructs( out size, out outArray );
      MyStruct[] manArray = new MyStruct[ size ];
      IntPtr current = outArray;
      for( int i = 0; i < size; i++ )
      {
         manArray[ i ] = new MyStruct();
         Marshal.PtrToStructure( current, manArray[ i ]);
         
         //Marshal.FreeCoTaskMem( (IntPtr)Marshal.ReadInt32( current ));
         Marshal.DestroyStructure( current, typeof(MyStruct) );
         current = (IntPtr)((long)current + 
            Marshal.SizeOf( manArray[ i ] ));
         
         Console.WriteLine( "Element {0}: {1} {2}", i, 
            manArray[ i ].buffer, manArray[ i ].size );
      }
      Marshal.FreeCoTaskMem( outArray );
   }
   
   public static unsafe void UsingUnsafe()
   {
      int size;
      MyUnsafeStruct* pResult;
      LibWrap.TestOutArrayOfStructs( out size, &pResult );
      MyUnsafeStruct* pCurrent = pResult;
      for( int i = 0; i < size; i++, pCurrent++ )
      {
         Console.WriteLine( "Element {0}: {1} {2}", i, 
            Marshal.PtrToStringAnsi( pCurrent->buffer ), pCurrent->size );
         Marshal.FreeCoTaskMem( pCurrent->buffer );
      }
      Marshal.FreeCoTaskMem( (IntPtr)pResult );
   }
}

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