Compartir a través de


Ejemplo Strings

Actualización: noviembre 2007

En este ejemplo se muestra cómo utilizar una cadena devuelta desde una función no administrada y cómo pasar una estructura que contiene una cadena con formato Unicode o con formato ANSI. Se muestra cómo inicializar correctamente estas cadenas y cómo recuperar los valores devueltos.

En el ejemplo String se utilizan las siguientes funciones no administradas, que se muestran con su declaración de función original:

  • TestStringAsResult exportada desde PinvokeLib.dll.

    char* TestStringAsResult();
    
  • TestStringInStruct exportada desde PinvokeLib.dll.

    void TestStringInStruct(MYSTRSTRUCT* pStruct);
    
  • TestStringInStructAnsi exportada desde PinvokeLib.dll.

    void TestStringInStructAnsi(MYSTRSTRUCT2* pStruct);
    

PinvokeLib.dll es una biblioteca personalizada y no administrada que contiene implementaciones para las funciones enumeradas anteriormente y dos estructuras: MYSTRSTRUCT y MYSTRSTRUCT2. Estas estructuras contienen los siguientes elementos:

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

En este ejemplo, las estructuras administradas MyStrStruct y MyStrStruct2 contienen cadenas administradas en lugar de búferes StringBuilder, porque el tipo StringBuilder no se puede utilizar dentro de una estructura. El atributo StructLayoutAttribute se establece para garantizar que los miembros se organizan secuencialmente en la memoria, en el orden en que aparecen. El campo CharSet se establece para especificar el formato ANSI o Unicode.

La clase LibWrap contiene los métodos de prototipo administrados a los que llama la clase App. Aunque las estructuras se suelen pasar por valor, los argumentos para los métodos TestStringInStruct y TestStringInStructAnsi se marcan con la palabra clave ref (ByRef en Visual Basic), que pasa las estructuras por referencia.

El código fuente de los ejemplos de código siguientes lo proporciona el Ejemplo de tecnología de invocación de plataformas de .NET Framework.

Declaración de prototipos

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

Llamadas a funciones

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

Vea también

Tareas

Ejemplo de tecnología de invocación de plataformas

Conceptos

Calcular referencias de cadenas

Tipos de datos de invocación de plataforma

Cálculo de referencias predeterminado para cadenas

Crear prototipos en código administrado