Partager via


Strings, exemple

Cet exemple montre comment utiliser une chaîne retournée à partir d'une fonction non managée, et comment passer une structure qui contient une chaîne au format Unicode ou au format ANSI. Il montre comment initialiser correctement ces chaînes et comment extraire des valeurs retournées.

L'exemple String utilise les fonctions non managées suivantes, illustrées avec leur déclaration de fonction d'origine :

  • TestStringAsResult exportée à partir de PinvokeLib.dll.

    char* TestStringAsResult();
    
  • TestStringInStruct exportée à partir de PinvokeLib.dll.

    void TestStringInStruct(MYSTRSTRUCT* pStruct);
    
  • TestStringInStructAnsi exportée à partir de PinvokeLib.dll.

    void TestStringInStructAnsi(MYSTRSTRUCT2* pStruct);
    

PinvokeLib.dll est une bibliothèque non managée personnalisée qui contient des implémentations pour les fonctions précédemment répertoriées et les deux structures MYSTRSTRUCT et MYSTRSTRUCT2. Ces structures contiennent les éléments suivants :

typedef struct _MYSTRSTRUCT
{
   wchar_t* buffer;
   UINT size; 
} MYSTRSTRUCT;
typedef struct _MYSTRSTRUCT2
{
   char* buffer;
   UINT size; 
} MYSTRSTRUCT2;

Dans cet exemple, les structures managées MyStrStruct et MyStrStruct2 contiennent des chaînes managées au lieu des mémoires tampons StringBuilder car le type StringBuilder ne peut pas s'utiliser au sein d'une structure. L'attribut StructLayoutAttribute est défini afin de garantir que les membres soient disposés en mémoire de manière séquentielle, dans l'ordre de leur apparition. Le champ CharSet est défini de façon à spécifier des formats ANSI ou Unicode.

La classe LibWrap contient les méthodes de prototype managé appelées par la classe App. Bien que les structures soient normalement passées par valeur, les arguments vers les méthodes TestStringInStruct et TestStringInStructAnsi sont marqués avec le mot clé ref (ByRef en Visual Basic) qui passe les structures par référence.

Le code source pour les exemples de code suivants est fourni par Appel de plate-forme, exemple de technologie du .NET Framework.

Déclaration de prototypes

' Declares a managed structure for each unmanaged structure.
< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Unicode )> _
Public Structure MyStrStruct
   Public buffer As String
   Public size As Integer
End Structure 'MyStrStruct

< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Ansi )> _
Public Structure MyStrStruct2
   Public buffer As String
   Public size As Integer
End Structure 'MyStrStruct2

Public Class LibWrap
   ' Declares managed prototypes for unmanaged functions.
   Declare Function TestStringAsResult Lib "..\LIB\PinvokeLib.dll" () _
      As String
   Declare Sub TestStringInStruct Lib "..\LIB\PinvokeLib.dll" _
      ( ByRef mss As MyStrStruct )
   Declare Sub TestStringInStructAnsi Lib "..\LIB\PinvokeLib.dll" _
      ( ByRef mss As MyStrStruct2 )
End Class 'LibWrap
// Declares a managed structure for each unmanaged structure.
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Unicode )]
public struct MyStrStruct 
{  
   public String buffer;
   public int size;
}
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct MyStrStruct2 
{  
   public String buffer;
   public int size;
}
public class LibWrap
{
   // Declares managed prototypes for unmanaged functions.
   [DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern String TestStringAsResult();

   [DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern void TestStringInStruct( ref MyStrStruct mss );

   [DllImport( "..\\LIB\\PinvokeLib.dll" )]
   public static extern void TestStringInStructAnsi( ref MyStrStruct2 
      mss );
}

Appel de fonctions

Public Class App
   Public Shared Sub Main()
      ' String as result.
      Dim strng As String = LibWrap.TestStringAsResult()
      Console.WriteLine( ControlChars.CrLf + "String returned: {0}", _
      strng )

      ' Initializes buffer and appends something to the end so the whole
      ' buffer is passed to the unmanaged side.
      Dim buffer As New StringBuilder( "content", 100 )
      buffer.Append( ChrW(0) )
      buffer.Append( "*"c, buffer.Capacity - 8)
      
      Dim mss As MyStrStruct
      mss.buffer = buffer.ToString()
      mss.size = mss.buffer.Length
      
      LibWrap.TestStringInStruct( mss )
      Console.WriteLine( ControlChars.CrLf + _
         "Buffer after Unicode function call: {0}", mss.buffer )

      Dim buffer2 As New StringBuilder( "content", 100 )
      buffer2.Append( ChrW(0) )
      buffer2.Append( "*"c, buffer2.Capacity - 8 )
      
      Dim mss2 As MyStrStruct2
      mss2.buffer = buffer2.ToString()
      mss2.size = mss2.buffer.Length 
      
      LibWrap.TestStringInStructAnsi( mss2 )
      Console.WriteLine( ControlChars.CrLf + _
         "Buffer after Ansi function call: {0}", mss2.buffer )
   End Sub 'Main
End Class 'App
public class App
{
   public static void Main()
   {
      // String as result.
      String str = LibWrap.TestStringAsResult();
      Console.WriteLine( "\nString returned: {0}", str );
      
      // Initializes buffer and appends something to the end so the whole
      // buffer is passed to the unmanaged side.
      StringBuilder buffer = new StringBuilder( "content", 100 ); 
      buffer.Append( (char)0 );
      buffer.Append( '*', buffer.Capacity - 8 );
      
      MyStrStruct mss;
      mss.buffer = buffer.ToString();
      mss.size = mss.buffer.Length;
      
      LibWrap.TestStringInStruct( ref mss );
      Console.WriteLine( "\nBuffer after Unicode function call: {0}", 
         mss.buffer );
      
      StringBuilder buffer2 = new StringBuilder( "content", 100 ); 
      buffer2.Append( (char)0 );
      buffer2.Append( '*', buffer2.Capacity - 8 );
      
      MyStrStruct2 mss2;
      mss2.buffer = buffer2.ToString();
      mss2.size = mss2.buffer.Length;
      
      LibWrap.TestStringInStructAnsi( ref mss2 );
      Console.WriteLine( "\nBuffer after Ansi function call: {0}", 
         mss2.buffer );
   }
}

Voir aussi

Tâches

Appel de plate-forme, exemple de technologie

Concepts

Marshaling de chaînes
Types de données d'appel de plate-forme
Marshaling par défaut pour les chaînes
Création de prototypes dans du code managé