marshaling de tipos diferentes de arrays
Este exemplo demonstra como passar os seguintes tipos de arrays:
Matriz de inteiros por valor.
Matriz de inteiros por referência, que pode ser redimensionada.
Matriz multidimensional (matriz) de inteiros por valor.
Matriz de seqüências de caracteres por valor.
Matriz de estruturas com números inteiros.
Matriz de estruturas com seqüências de caracteres.
A menos que explicitamente uma matriz é empacotada por referência, o comportamento padrão empacota o array sistema autônomo um parâmetro de entrada.Você pode alterar esse comportamento, aplicando o InAttribute e OutAttribute atributos explicitamente.
O exemplo de arrays utiliza as seguintes funções não gerenciadas, mostradas com sua declaração de função original:
TestArrayOfInts exportados de PinvokeLib.dll.
int TestArrayOfInts(int* pArray, int pSize);
TestRefArrayOfInts exportados de PinvokeLib.dll.
int TestRefArrayOfInts(int** ppArray, int* pSize);
TestMatrixOfInts exportados de PinvokeLib.dll.
int TestMatrixOfInts(int pMatrix[][COL_DIM], int row);
TestArrayOfStrings exportados de PinvokeLib.dll.
int TestArrayOfStrings(char** ppStrArray, int size);
TestArrayOfStructs exportados de PinvokeLib.dll.
int TestArrayOfStructs(MYPOINT* pPointArray, int size);
TestArrayOfStructs2 exportados de PinvokeLib.dll.
int TestArrayOfStructs2 (MYPERSON* pPersonArray, int size);
PinvokeLib.dll é uma biblioteca de não gerenciada personalizada que contém implementações para as funções listadas anteriormente e duas variáveis de estrutura, MYPOINT and MYPERSON.As estruturas de contenham os seguintes elementos:
typedef struct _MYPOINT
{
int x;
int y;
} MYPOINT;
typedef struct _MYPERSON
{
char* first;
char* last;
} MYPERSON;
Neste exemplo, a MyPoint e MyPerson estruturas contêm tipos incorporados. The StructLayoutAttribute atributo é definido para garantir que os membros são organizados em memória seqüencialmente, na ordem em que aparecem.
The LibWrap classe contém um conjunto de métodos chamados App classe. Para obter detalhes específicos sobre matrizes de passagem, consulte os comentários no exemplo a seguir.Uma matriz, que é um tipo de referência, é passada sistema autônomo um parâmetro de entrada por padrão.Para o chamador receber os resultados, InAttribute and OutAttribute devem ser aplicadas explicitamente para o argumento que contém a matriz.
O código-fonte para os exemplos de código a seguir é fornecido pelo.NET estrutura Invocação de plataforma Tecnologia Exemplo.
Declaração de protótipos
' Declares a managed structure for each unmanaged structure.
< StructLayout( LayoutKind.Sequential )> _
Public Structure MyPoint
Public x As Integer
Public y As Integer
Public Sub New( x As Integer, y As Integer )
Me.x = x
Me.y = y
End Sub 'New
End Structure 'MyPoint
< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Ansi )> _
Public Structure MyPerson
Public first As String
Public last As String
Public Sub New( first As String, last As String )
Me.first = first
Me.last = last
End Sub 'New
End Structure 'MyPerson
Public Class LibWrap
' Declares a managed prototype for an array of integers by value.
' The array size cannot be changed, but the array is copied back.
Declare Function TestArrayOfInts Lib "..\LIB\PinvokeLib.dll" ( _
<[In], Out> ByVal myArray() As Integer, ByVal size As Integer ) _
As Integer
' Declares managed prototype for an array of integers by reference.
' The array size can change, but the array is not copied back
' automatically because the marshaler does not know the resulting size.
' The copy must be performed manually.
Declare Function TestRefArrayOfInts Lib "..\LIB\PinvokeLib.dll" ( _
ByRef myArray As IntPtr, ByRef size As Integer ) As Integer
' Declares a managed prototype for a matrix of integers by value.
Declare Function TestMatrixOfInts Lib "..\LIB\PinvokeLib.dll" ( _
<[In], Out> ByVal matrix(,) As Integer, ByVal row As Integer ) _
As Integer
' Declares a managed prototype for an array of strings by value.
Declare Function TestArrayOfStrings Lib "..\LIB\PinvokeLib.dll" ( _
<[In], Out> ByVal strArray() As String, ByVal size As Integer ) _
As Integer
' Declares a managed prototype for an array of structures with
' integers.
Declare Function TestArrayOfStructs Lib "..\LIB\PinvokeLib.dll" ( _
<[In], Out> ByVal pointArray() As MyPoint, _
ByVal size As Integer ) As Integer
' Declares a managed prototype for an array of structures with strings.
Declare Function TestArrayOfStructs2 Lib "..\LIB\PinvokeLib.dll" ( _
<[In], Out> ByVal personArray() As MyPerson, ByVal size _
As Integer ) As Integer
End Class 'LibWrap
// Declares a managed structure for each unmanaged structure.
[ StructLayout( LayoutKind.Sequential )]
public struct MyPoint
{
public int x;
public int y;
public MyPoint( int x, int y )
{
this.x = x;
this.y = y;
}
}
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct MyPerson
{
public String first;
public String last;
public MyPerson( String first, String last )
{
this.first = first;
this.last = last;
}
}
public class LibWrap
{
// Declares a managed prototype for an array of integers by value.
// The array size cannot be changed, but the array is copied back.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestArrayOfInts([In, Out] int[] array, int size );
// Declares a managed prototype for an array of integers by reference.
// The array size can change, but the array is not copied back
// automatically because the marshaler does not know the resulting size.
// The copy must be performed manually.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestRefArrayOfInts( ref IntPtr array,
ref int size );
// Declares a managed prototype for a matrix of integers by value.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestMatrixOfInts([In, Out] int[,] pMatrix,
int row );
// Declares a managed prototype for an array of strings by value.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestArrayOfStrings( [In, Out]
String[] stringArray, int size );
// Declares a managed prototype for an array of structures with integers.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestArrayOfStructs([In, Out] MyPoint[]
pointArray, int size );
// Declares a managed prototype for an array of structures with strings.
[ DllImport( "..\\LIB\\PinvokeLib.dll" )]
public static extern int TestArrayOfStructs2( [In, Out]
MyPerson[] personArray, int size );
}
Chamando funções
Public Class App
Public Shared Sub Main()
' array ByVal
Dim array1(9) As Integer
Console.WriteLine( "Integer array passed ByVal before call:" )
Dim i As Integer
For i = 0 To array1.Length - 1
array1(i) = i
Console.Write( " " & array1(i) )
Next i
Dim sum1 As Integer = LibWrap.TestArrayOfInts( array1, array1._
Length )
Console.WriteLine( ControlChars.CrLf & "Sum of elements:" & sum1 )
Console.WriteLine( ControlChars.CrLf & "Integer array passed _
ByVal after call:" )
For Each i In array1
Console.Write( " " & i )
Next i
' array ByRef
Dim array2(9) As Integer
Dim arraySize As Integer = array2.Length
Console.WriteLine( ControlChars.CrLf & ControlChars.CrLf & _
"Integer array passed ByRef before call:" )
For i = 0 To array2.Length - 1
array2(i) = i
Console.Write( " " & array2(i) )
Next i
Dim buffer As IntPtr = Marshal.AllocCoTaskMem( Marshal.SizeOf( _
arraySize ) * array2.Length )
Marshal.Copy( array2, 0, buffer, array2.Length )
Dim sum2 As Integer = LibWrap.TestRefArrayOfInts( buffer, _
arraySize )
Console.WriteLine( ControlChars.CrLf & "Sum of elements:" & sum2 )
If arraySize > 0 Then
Dim arrayRes( arraySize - 1 ) As Integer
Marshal.Copy( buffer, arrayRes, 0, arraySize )
Marshal.FreeCoTaskMem( buffer )
Console.WriteLine( ControlChars.CrLf & "Integer array _
passed ByRef after call:" )
For Each i In arrayRes
Console.Write( " " & i )
Next i
Else
Console.WriteLine( ControlChars.CrLf & "Array after call _
is empty" )
End If
' matrix ByVal
Const [DIM] As Integer = 4
Dim matrix([DIM], [DIM]) As Integer
Console.WriteLine( ControlChars.CrLf & ControlChars.CrLf & _
"Matrix before call:" )
For i = 0 To [DIM]
Dim j As Integer
For j = 0 To [DIM]
matrix(i, j) = j
Console.Write( " " & matrix(i, j) )
Next j
Console.WriteLine( "" )
Next i
Dim sum3 As Integer = LibWrap.TestMatrixOfInts( matrix, [DIM] + 1 )
Console.WriteLine( ControlChars.CrLf & "Sum of elements:" & sum3 )
Console.WriteLine( ControlChars.CrLf & "Matrix after call:" )
For i = 0 To [DIM]
Dim j As Integer
For j = 0 To [DIM]
Console.Write( " " & matrix(i, j) )
Next j
Console.WriteLine( "" )
Next i
' string array ByVal
Dim strArray As String() = { "one", "two", "three", "four", _
"five" }
Console.WriteLine( ControlChars.CrLf & ControlChars.CrLf & _
"String array before call:" )
Dim s As String
For Each s In strArray
Console.Write( " " & s )
Next s
Dim lenSum As Integer = LibWrap.TestArrayOfStrings( _
strArray, strArray.Length )
Console.WriteLine( ControlChars.CrLf & _
"Sum of string lengths:" & lenSum )
Console.WriteLine( ControlChars.CrLf & "String array after call:" )
For Each s In strArray
Console.Write( " " & s )
Next s
' struct array ByVal
Dim points As MyPoint() = { New MyPoint(1, 1), New MyPoint(2, 2), _
New MyPoint(3, 3) }
Console.WriteLine( ControlChars.CrLf & ControlChars.CrLf & _
"Points array before call:" )
Dim p As MyPoint
For Each p In points
Console.WriteLine( "x = {0}, y = {1}", p.x, p.y )
Next p
Dim allSum As Integer = LibWrap.TestArrayOfStructs( points, _
points.Length )
Console.WriteLine( ControlChars.CrLf & "Sum of points:" & allSum )
Console.WriteLine( ControlChars.CrLf & "Points array after call:" )
For Each p In points
Console.WriteLine( "x = {0}, y = {1}", p.x, p.y )
Next p
' struct with strings array ByVal
Dim persons As MyPerson() = { _New MyPerson( "Kim", "Akers" ), _
New MyPerson( "Adam", "Barr" ), _
New MyPerson( "Jo", "Brown" )}
Console.WriteLine( ControlChars.CrLf & ControlChars.CrLf & _
"Persons array before call:" )
Dim pe As MyPerson
For Each pe In persons
Console.WriteLine( "first = {0}, last = {1}", pe.first, pe.last )
Next pe
Dim namesSum As Integer = LibWrap.TestArrayOfStructs2( persons, _
persons.Length )
Console.WriteLine( ControlChars.CrLf & "Sum of name lengths:" & _
namesSum )
Console.WriteLine( ControlChars.CrLf & ControlChars._
CrLf & "Persons array after call:" )
For Each pe In persons
Console.WriteLine( "first = {0}, last = {1}", pe.first, pe.last )
Next pe
End Sub 'Main
End Class 'App
public class App
{
public static void Main()
{
// array ByVal
int[] array1 = new int[ 10 ];
Console.WriteLine( "Integer array passed ByVal before call:" );
for( int i = 0; i < array1.Length; i++ )
{
array1[ i ] = i;
Console.Write( " " + array1[ i ] );
}
int sum1 = LibWrap.TestArrayOfInts( array1, array1.Length );
Console.WriteLine( "\nSum of elements:" + sum1 );
Console.WriteLine( "\nInteger array passed ByVal after call:" );
foreach( int i in array1 )
{
Console.Write( " " + i );
}
// array ByRef
int[] array2 = new int[ 10 ];
int size = array2.Length;
Console.WriteLine( "\n\nInteger array passed ByRef before call:" );
for( int i = 0; i < array2.Length; i++ )
{
array2[ i ] = i;
Console.Write( " " + array2[ i ] );
}
IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( size )
* array2.Length );
Marshal.Copy( array2, 0, buffer, array2.Length );
int sum2 = LibWrap.TestRefArrayOfInts( ref buffer, ref size );
Console.WriteLine( "\nSum of elements:" + sum2 );
if( size > 0 )
{
int[] arrayRes = new int[ size ];
Marshal.Copy( buffer, arrayRes, 0, size );
Marshal.FreeCoTaskMem( buffer );
Console.WriteLine( "\nInteger array passed ByRef after call:" );
foreach( int i in arrayRes )
{
Console.Write( " " + i );
}
}
else
Console.WriteLine( "\nArray after call is empty" );
// matrix ByVal
const int DIM = 5;
int[,] matrix = new int[ DIM, DIM ];
Console.WriteLine( "\n\nMatrix before call:" );
for( int i = 0; i < DIM; i++ )
{
for( int j = 0; j < DIM; j++ )
{
matrix[ i, j ] = j;
Console.Write( " " + matrix[ i, j ] );
}
Console.WriteLine( "" );
}
int sum3 = LibWrap.TestMatrixOfInts( matrix, DIM );
Console.WriteLine( "\nSum of elements:" + sum3 );
Console.WriteLine( "\nMatrix after call:" );
for( int i = 0; i < DIM; i++ )
{
for( int j = 0; j < DIM; j++ )
{
Console.Write( " " + matrix[ i, j ] );
}
Console.WriteLine( "" );
}
// string array ByVal
String[] strArray = { "one", "two", "three", "four", "five" };
Console.WriteLine( "\n\nString array before call:" );
foreach( String s in strArray )
Console.Write( " "+ s );
int lenSum = LibWrap.TestArrayOfStrings( strArray, strArray.Length );
Console.WriteLine( "\nSum of string lengths:" + lenSum );
Console.WriteLine( "\nString array after call:" );
foreach( String s in strArray )
{
Console.Write( " " + s );
}
// struct array ByVal
MyPoint[] points = { new MyPoint(1,1), new MyPoint(2,2), new MyPoint(3,3) };
Console.WriteLine( "\n\nPoints array before call:" );
foreach( MyPoint p in points )
Console.WriteLine( "x = {0}, y = {1}", p.x, p.y );
int allSum = LibWrap.TestArrayOfStructs( points, points.Length );
Console.WriteLine( "\nSum of points:" + allSum );
Console.WriteLine( "\nPoints array after call:" );
foreach( MyPoint p in points )
Console.WriteLine( "x = {0}, y = {1}", p.x, p.y );
// struct with strings array ByVal
MyPerson[] persons = { new MyPerson( "Kim", "Akers" ),
new MyPerson( "Adam", "Barr" ), new MyPerson( "Jo", "Brown" )};
Console.WriteLine( "\n\nPersons array before call:" );
foreach( MyPerson pe in persons )
Console.WriteLine( "first = {0}, last = {1}", pe.first, pe.last );
int namesSum = LibWrap.TestArrayOfStructs2( persons, persons.Length );
Console.WriteLine( "\nSum of name lengths:" + namesSum );
Console.WriteLine( "\n\nPersons array after call:" );
foreach( MyPerson pe in persons )
Console.WriteLine( "first = {0}, last = {1}", pe.first, pe.last );
}
}
Consulte também
Conceitos
marshaling de matrizes de tipos