Amostra de OutArrayOfStructs
Este exemplo mostra como passar uma matriz de estruturas que contém números inteiros e seqüências de caracteres como parâmetros para uma função não gerenciada.
Este exemplo demonstra como chamar uma função nativa usando o Marshal de classe e usando código não seguro.
Este exemplo utiliza a funções de wrapper e platform invokes definido em PinvokeLib.dll, também é fornecida em arquivos de origem. 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;
O MyStruct classe contém um objeto de seqüência de caracteres de ANSI. O CharSet campo especifica o formato de ANSI. MyUnsafeStruct, é uma estrutura que contém um IntPtr tipo em vez de uma seqüência de caracteres.
O LibWrap classe contém o sobrecarregado TestOutArrayOfStructs método de protótipo. Se um método declara um ponteiro como 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 inseguro e o MyUnsafeStruct estrutura são desnecessários.
O App classe implementa o UsingMarshaling método, que executa todas as tarefas necessárias para passar o array. A matriz é marcada com o out (ByRef em Visual Basic) passa de palavra-chave para indicar que os dados do chamador para o chamador. A implementação usa a seguinte Marshal métodos de classe:
PtrToStructurepara empacotar dados no buffer não gerenciado em um objeto gerenciado.
DestroyStructurePara liberar a memória reservada para seqüências de caracteres na estrutura.
FreeCoTaskMemPara liberar a memória reservada para a matriz.
Como mencionado anteriormente, C# permite que o código não seguro e Visual Basic 2005 faz não. No exemplo de C#, UsingUnsafePointer é 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.
A 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);
}
// Declares a class member for each structure element.
[StructLayout(LayoutKind::Sequential, CharSet=CharSet::Ansi)]
public ref class MyStruct
{
public:
String^ buffer;
int size;
};
// Declares a structure with a pointer.
[StructLayout(LayoutKind::Sequential)]
public value struct MyUnsafeStruct
{
public:
IntPtr buffer;
int size;
};
public ref class LibWrap
{
public:
// Declares managed prototypes for the unmanaged function.
[DllImport("..\\LIB\\PInvokeLib.dll")]
static void TestOutArrayOfStructs(int% size,
IntPtr% outArray);
[DllImport("..\\LIB\\PInvokeLib.dll")]
static void TestOutArrayOfStructs(int% size,
MyUnsafeStruct** outArray);
};
Chamando funções
Public Class App
Public Shared Sub Main()
Console.WriteLine( vbNewLine + "Using marshal class" + vbNewLine)
UsingMarshaling()
'Visual Basic 2005 cannot use unsafe code.
End Sub 'Main
Public Shared Sub UsingMarshaling()
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");
UsingMarshaling();
Console.WriteLine("\nUsing unsafe code\n");
UsingUnsafePointer();
}
public static void UsingMarshaling()
{
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 UsingUnsafePointer()
{
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);
}
}
public ref class App
{
public:
static void Main()
{
Console::WriteLine("\nUsing marshal class\n");
UsingMarshaling();
Console::WriteLine("\nUsing unsafe code\n");
UsingUnsafePointer();
}
static void UsingMarshaling()
{
int size;
IntPtr outArray;
LibWrap::TestOutArrayOfStructs(size, outArray);
array<MyStruct^>^ manArray = gcnew array<MyStruct^>(size);
IntPtr current = outArray;
for (int i = 0; i < size; i++)
{
manArray[i] = gcnew MyStruct();
Marshal::PtrToStructure(current, manArray[i]);
Marshal::DestroyStructure(current, MyStruct::typeid);
//current = (IntPtr)((long)current + Marshal::SizeOf(manArray[i]));
current = current + Marshal::SizeOf(manArray[i]);
Console::WriteLine("Element {0}: {1} {2}", i, manArray[i]->buffer,
manArray[i]->size);
}
Marshal::FreeCoTaskMem(outArray);
}
static void UsingUnsafePointer()
{
int size;
MyUnsafeStruct* pResult;
LibWrap::TestOutArrayOfStructs(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
O empacotamento de Classes, estruturas e uniões