Questo articolo è stato tradotto automaticamente. Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

Esempio di strutture

In questo esempio viene dimostrato come passare una struttura che punta a una seconda struttura, una struttura con una struttura incorporata e una struttura con una matrice incorporata.

Nell'esempio di strutture vengono utilizzate le seguenti funzioni non gestite, illustrate con le dichiarazioni di funzione originali:

  • TestStructInStruct esportata da PinvokeLib.dll.

    int TestStructInStruct(MYPERSON2* pPerson2);
    
  • TestStructInStruct3 esportata da PinvokeLib.dll.

    void TestStructInStruct3(MYPERSON3 person3);
    
  • TestArrayInStruct esportata da PinvokeLib.dll.

    void TestArrayInStruct( MYARRAYSTRUCT* pStruct );
    

PinvokeLib.dll è una libreria non gestita personalizzata contenente implementazioni per le funzioni elencate in precedenza e quattro strutture, ovvero MYPERSON, MYPERSON2, MYPERSON3 e MYARRAYSTRUCT, le quali contengono i seguenti elementi:

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;

Le strutture gestite MyPerson, MyPerson2, MyPerson3 e MyArrayStruct hanno le seguenti caratteristiche:

  • MyPerson contiene solo membri stringa. Le stringhe vengono impostate sul formato ANSI dal campo CharSet, quando viene passato alla funzione non gestita.

  • MyPerson2 contiene un tipo IntPtr alla struttura MyPerson. Il tipo IntPtr sostituisce il puntatore originale alla struttura non gestita poiché nelle applicazioni .NET Framework non vengono utilizzati i puntatori a meno che il codice non sia contrassegnato come unsafe.

  • MyPerson3 contiene MyPerson come struttura incorporata. È possibile semplificare una struttura incorporata in un'altra struttura posizionandone gli elementi direttamente nella struttura principale oppure mantenerla incorporata, come accade in questo esempio.

  • MyArrayStruct contiene una matrice di integer. Il valore dell'enumerazione UnmanagedType viene impostato dall'attributo MarshalAsAttribute su ByValArray, che consente di indicare il numero di elementi nella matrice.

Per tutte le strutture di questo esempio, l'attributo StructLayoutAttribute viene applicato in modo che i membri vengano disposti in sequenza nella memoria, nell'ordine in cui appaiono.

La classe LibWrap contiene prototipi gestiti per i metodi TestStructInStruct, TestStructInStruct3 e TestArrayInStruct chiamati dalla classe App. Ciascun prototipo dichiara un singolo parametro, come indicato di seguito:

  • TestStructInStruct dichiara un riferimento al tipo MyPerson2 come parametro.

  • TestStructInStruct3 dichiara il tipo MyPerson3 come parametro e passa il parametro per valore.

  • TestArrayInStruct dichiara un riferimento al tipo MyArrayStruct come parametro.

Come argomenti per i metodi, le strutture vengono passate per valore a meno che il parametro non contenga la parola chiave ref (ByRef in Visual Basic). Ad esempio, il metodo TestStructInStruct passa un riferimento, ossia il valore di un indirizzo, a un oggetto di tipo MyPerson2 al codice non gestito. Per modificare la struttura alla quale punta MyPerson2, nell'esempio viene creato un buffer di dimensioni specificate e ne viene restituito l'indirizzo combinando i metodi Marshal.AllocCoTaskMem e Marshal.SizeOf. In seguito, il contenuto della struttura gestita viene copiato nel buffer non gestito. Infine, il metodo Marshal.PtrToStructure viene utilizzato per effettuare il marshalling dei dati dal buffer non gestito in un oggetto gestito, mentre il metodo Marshal.FreeCoTaskMem viene utilizzato per liberare il blocco di memoria non gestito.


// 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);
}



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 = "Evans";
        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]);
    }
}


Mostra: