Condividi tramite


Esempio di buffer

In questo esempio viene illustrato come passare le stringhe come parametri in/out alle funzioni non gestite per le quali è prevista una stringa (LPSTR) come parametro di funzione. Viene inoltre illustrato come utilizzare una stringa restituita da un metodo non gestito nel caso in cui non è previsto che il chiamante liberi la memoria allocata per la stringa.

Questa piattaforma di esempio richiama due funzioni Win32 native esportate da Kernel32.dll:

  • GetSystemDirectory

    Recupera il percorso della directory di sistema.

  • GetCommandLine

    Recupera la stringa della riga di comando del processo corrente.

Nella classe LibWrap sono contenuti prototipi gestiti per le funzioni non gestite, che vengono chiamate dal metodo Main nell'applicazione console. Il campo CharSet viene impostato in modo che in pInvoke possa essere effettuata la scelta tra i formati ANSI e Unicode in fase di esecuzione, in base alla piattaforma di destinazione. Per ulteriori informazioni su questo campo, vedere Specifica di un set di caratteri.

Nel metodo prototipo GetSystemDirectory il tipo non gestito LPSTR è sostituito da un buffer StringBuilder. Le dimensioni del buffer rimangono fisse. Per soddisfare i requisiti della funzione originale, GetSystemDirectory passa la variabile della dimensione del buffer come secondo argomento. Nella dichiarazione il tipo LPTSTR viene sostituito da un buffer StringBuilder anziché da una stringa. A differenza delle stringhe, che sono immutabili, i buffer StringBuilder possono essere modificati.

La funzione GetCommandLine nativa restituisce un puntatore a un buffer allocato e di proprietà del sistema operativo. Nel marshalling delle stringhe come tipi restituiti il gestore di marshalling di interoperabilità presuppone che sia necessario liberare la memoria a cui punta il tipo LPTSTR tramite la funzione. Per evitare il recupero automatico di questa memoria da parte del gestore di marshalling, il prototipo GetCommandLine gestito restituisce un tipo IntPtr anziché una stringa. Con il metodo PtrToStringAuto il tipo LPSTR non gestito viene copiato in un oggetto stringa gestita, con l'ampliamento del formato di carattere, se necessario.

Dichiarazione dei prototipi

Public Class LibWrap
    Declare Auto Sub GetSystemDirectory Lib "Kernel32.dll" _
        (ByVal sysDirBuffer As StringBuilder, ByVal buffSize As Integer)

    Declare Auto Function GetCommandLine Lib "Kernel32.dll" () As IntPtr
End Class
public class LibWrap
{
    [DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
    public static extern int GetSystemDirectory(StringBuilder
        sysDirBuffer, int size);

    [DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
    public static extern IntPtr GetCommandLine();
}
public ref class LibWrap
{
public:
    [DllImport("Kernel32.dll", CharSet=CharSet::Auto)]
    static int GetSystemDirectory(StringBuilder^
        sysDirBuffer, int size);

    [DllImport("Kernel32.dll", CharSet=CharSet::Auto)]
    static IntPtr GetCommandLine();
};

Chiamata delle funzioni

Public Class App
    Public Shared Sub Main()
        ' Call GetSystemDirectory.
        Dim sysDirBuffer As New StringBuilder(256)
        LibWrap.GetSystemDirectory(sysDirBuffer, sysDirBuffer.Capacity)
        ' ...
        ' Call GetCommandLine.
        Dim cmdLineStr As IntPtr = LibWrap.GetCommandLine()
        Dim commandLine As String = Marshal.PtrToStringAuto(cmdLineStr)
    End Sub
End Class
public class App
{
    public static void Main()
    {
        // Call GetSystemDirectory.
        StringBuilder sysDirBuffer = new StringBuilder(256);
        LibWrap.GetSystemDirectory(sysDirBuffer, sysDirBuffer.Capacity);
        // ...
        // Call GetCommandLine.
        IntPtr cmdLineStr = LibWrap.GetCommandLine();
        string commandLine = Marshal.PtrToStringAuto(cmdLineStr);
    }
}
public ref class App
{
public:
    static void Main()
    {
        // Call GetSystemDirectory.
        StringBuilder^ sysDirBuffer = gcnew StringBuilder(256);
        LibWrap::GetSystemDirectory(sysDirBuffer, sysDirBuffer->Capacity);
        // ...
        // Call GetCommandLine.
        IntPtr cmdLineStr = LibWrap::GetCommandLine();
        String^ commandLine = Marshal::PtrToStringAuto(cmdLineStr);
    }
};

Vedere anche

Concetti

Marshalling di stringhe

Tipi di dati di platform invoke

Marshalling predefinito per le stringhe

Altre risorse

Creating Prototypes in Managed Code