Share via


Mémoires tampons, exemple

Cet exemple montre comment passer des chaînes en tant que paramètres en entrée/sortie vers des fonctions non managées qui nécessitent une chaîne (LPSTR) comme paramètre de fonction. De plus, cet exemple montre comment utiliser une chaîne retournée à partir d'une méthode non managée dans le cas particulier ou l'appelant n'est pas censé libérer de la mémoire allouée à cette chaîne.

Cet exemple de code non managé appelle deux fonctions Win32 natives exportées à partir de Kernel32.dll :

  • GetSystemDirectory

    Récupère le chemin d'accès du répertoire système.

  • GetCommandLine

    Récupère la chaîne de ligne de commande pour le processus actuel.

La classe LibWrap contient des prototypes managés pour les fonctions non managées qui sont appelées à partir de Main dans l'application console. Le champ CharSet est défini de telle sorte que l'appel de code non managé peut choisir entre les formats Unicode et ANSI au moment de l'exécution, en fonction de la plateforme cible. Pour plus d'informations sur ce champ, consultez Spécification d'un jeu de caractères.

La méthode de prototype GetSystemDirectory remplace une mémoire tampon StringBuilder par le type LPSTR non managé. La taille de la mémoire tampon reste fixe. Pour satisfaire aux exigences de la fonction d'origine, GetSystemDirectory passe la variable taille de la mémoire tampon comme deuxième argument. Une mémoire tampon StringBuilder, plutôt qu'une chaîne, remplace le type LPTSTR dans la déclaration. Contrairement aux chaînes, qui sont immuables, les mémoires tampons StringBuilder peuvent être changées.

La fonction GetCommandLine native retourne un pointeur vers une mémoire tampon allouée et détenue par le système d'exploitation. Lors du marshaling des chaînes comme types de retour, le marshaleur d'interopérabilité suppose qu'il doit libérer la mémoire vers laquelle le type LPTSTR d'origine pointait par la fonction. Pour éviter que le marshaleur ne récupère automatiquement cette mémoire, le prototype managé GetCommandLine retourne un type IntPtr au lieu d'une chaîne. La méthode PtrToStringAuto copie le type LPSTR non managé vers un objet chaîne managé, élargissant le format de caractère, si nécessaire.

Déclaration de prototypes

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

Fonctions d'appel

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

Voir aussi

Concepts

Marshaling de chaînes

Types de données d'appel de code non managé

Marshaling par défaut pour les chaînes

Autres ressources

Creating Prototypes in Managed Code