Condividi tramite


Esempio di wrapper di chiamata al sistema operativo

Aggiornamento: novembre 2007

Se una struttura contiene tipi semplici, può essere passata a una funzione nativa. La routine nativa deve essere conforme al modo in cui la struttura viene creata in .NET Compact Framework.

Si consideri una funzione nativa denominata DoRequest con un solo parametro, un puntatore a una struttura, che a sua volta definisce due campi:

  • Una matrice di caratteri contenente una stringa ANSI con terminazione NULL.

  • Un valore integer.

La struttura in C++ è la seguente:

typedef struct 
{
    char *RequestName,
    int   Count,
} ALERT_REQUEST;

int DoAlertRequest(ALERT_REQUEST *pRequest);

La versione gestita corrispondente in C# è:

struct AlertRequest
{
    String RequestName;
    int    Count;
}

class AlertClass
{
    [DLLImport("ALERT.DLL", EntryPoint="DoAlertRequest", 
        CharSet=CharacterSet.Ansi)]
    public static extern int DoRequest(ref AlertRequest Req);
}

L'attributo DllImportAttribute annota i metadati della chiamata al metodo nativo e segnala a Common Language Runtime che il metodo DoRequest si trova in ALERT.DLL, che il nome del metodo è DoAllertRequest e che è necessario eseguire il marshalling delle stringhe in formato ANSI poiché tutte le stringhe nel codice gestito sono di tipo Unicode.

Di seguito è riportato un esempio di chiamata a questo metodo eseguita in C++ con .NET Framework:

AlertRequest Request = new AlertRequest()
Request.RequestName = "beep";
Request.Count = 10;
AlertClass.DoRequest(ref Request);

Quando Common Language Runtime di .NET Framework rileva la chiamata a DoRequest, carica ALERT.DLL in modo dinamico, ottiene l'indirizzo di DoAlertRequest, genera la necessaria versione non gestita delle stringhe di conversione della struttura, esegue il push di un puntatore a tale struttura e chiama DoAlertRequest. Non è possibile passare semplicemente il puntatore alla struttura, poiché contiene un oggetto String incorporato.

A causa di queste limitazioni, non è possibile chiamare direttamente il metodo nativo DoRequest, ma è necessario eseguire una chiamata intermedia al thunk per incapsulare DoRequest. Di seguito viene riportato codice C# di esempio:

class AlertClass
{
    [DllImport("ALERT.DLL", EntryPoint="DoAlertRequestThunk")]
    private static extern int DoRequestThunk(String RequestName, int Count);

    public static int DoRequest(ref AlertRequst Req)
        {
            return DoRequestThunk(Req.RequestName, Req.Count);
        }
}

In AlertClass è ancora presente un metodo con la stessa firma della controparte in .NET Framework. Il metodo DoRequest di .NET Compact Framework è una routine gestita che consente di chiamare una routine nativa privata. Nella chiamata alla routine nativa i campi della struttura sono stati divisi in argomenti separati, poiché non è necessario eseguire il marshalling dell'oggetto String all'interno della struttura, e il thunk incapsula il metodo DoRequest nativo. Viene inoltre generata una versione non gestita della struttura e viene eseguita la conversione della stringa, come illustrato di seguito in C++:

int DoRequestThunk(wchar_t *RequestNameW, int Count)
{
    ALERT_REQUEST Req;
    int ReturnCode;
       
    // CreateAnsiFromUnicodeString allocates and builds an ANSI
    // version of the Unicode string.
    Req.RequestName = CreateAnsiFromUnicodeString(RequestNameW);
    if (Req.RequestName == NULL) 
        Return 0;

    Req.Count = Count;

    // This is the native DoRequest, not to be confused
    // with the managed method of the same name.
    ReturnCode = DoAlertRequest(&Req);

    free(Req.RequestName)
    return ReturnCode;
}

Vedere anche

Altre risorse

Supporto per le chiamate al sistema operativo