Partilhar via


Padrão de empacotamento de Strings

Tanto o System.String e System.Text.StringBuilder classes têm comportamento de empacotamento semelhantes.

Strings são empacotados como um estilo COM BSTR tipo ou como uma matriz de caracteres, uma referência nula de terminação (Nothing em Visual Basic). Dentro da seqüência de caracteres podem ser empacotados como Unicode ou ANSI ou de forma dependente de plataforma (Unicode em Windows NT de Microsoft Windows 2000 e Windows XP; ANSI no Windows 98 e Windows Millennium Edition (Windows Me).

Este tópico fornece as seguintes informações no empacotamento de tipos de seqüência de caracteres:

  • Seqüências de caracteres usadas nas Interfaces

  • Seqüências de caracteres usadas na plataforma Invoke

  • Seqüências de caracteres usadas em estruturas

  • Buffers de cadeia de caracteres de comprimento fixo

Seqüências de caracteres usadas nas Interfaces

A tabela a seguir mostra as opções de empacotamento para o tipo de dados de seqüência de caracteres quando empacotado como um argumento de método para código não gerenciado. O MarshalAsAttribute atributo fornece vários UnmanagedType valores de enumeração para empacotar strings para interfaces de COM.

Tipo de enumeração

Descrição do formato não gerenciado

UnmanagedType.BStr (padrão)

Um estilo COM BSTR com um comprimento prefixado e todos os caracteres Unicode.

UnmanagedType.LPStr

Um ponteiro para uma matriz de terminada por caractere nulo de caracteres ANSI.

UnmanagedType.LPWStr

Um ponteiro para uma matriz de caracteres Unicode terminada por caractere nulo.

Esta tabela se aplica a seqüências de caracteres. No entanto, para StringBuilder, as únicas opções permitidas são UnmanagedType.LPStr e UnmanagedType.LPWStr.

O exemplo a seguir mostra seqüências declaradas na IStringWorker interface.

public interface IStringWorker {
void PassString1(String s);
void PassString2([MarshalAs(UnmanagedType.BStr)]String s);
void PassString3([MarshalAs(UnmanagedType.LPStr)]String s);
void PassString4([MarshalAs(UnmanagedType.LPWStr)]String s);
void PassStringRef1(ref String s);
void PassStringRef2([MarshalAs(UnmanagedType.BStr)]ref String s);
void PassStringRef3([MarshalAs(UnmanagedType.LPStr)]ref String s);
void PassStringRef4([MarshalAs(UnmanagedType.LPWStr)]ref String s);
);

O exemplo a seguir mostra a interface correspondente, descrita em uma biblioteca de tipos.

[…]
interface IStringWorker : IDispatch {
HRESULT PassString1([in] BSTR s);
HRESULT PassString2([in] BSTR s);
HRESULT PassString3([in] LPStr s);
HRESULT PassString4([in] LPWStr s);
HRESULT PassStringRef1([in, out] BSTR *s);
HRESULT PassStringRef2([in, out] BSTR *s);
HRESULT PassStringRef3([in, out] LPStr *s);
HRESULT PassStringRef4([in, out] LPWStr *s);
);

Seqüências de caracteres usadas na plataforma Invoke

Argumentos de seqüência de caracteres de cópias, convertendo de invocação de plataforma a.Formato do NET Framework (Unicode) para o formato não gerenciado da plataforma. Seqüências de caracteres são imutáveis e não são copiadas de memória não gerenciada para gerenciado de memória quando a chamada retorna.

A tabela a seguir lista as opções de empacotamento para seqüências de caracteres quando empacotado como um argumento do método de uma plataforma de chamada de invocação. O MarshalAsAttribute atributo fornece vários UnmanagedType valores de enumeração para empacotar strings.

Tipo de enumeração

Descrição do formato não gerenciado

UnmanagedType.AnsiBStr

Um estilo COM BSTR com um comprimento prefixado e todos os caracteres ANSI.

UnmanagedType.BStr

Um estilo COM BSTR com um comprimento prefixado e todos os caracteres Unicode.

UnmanagedType.LPStr

Um ponteiro para uma matriz de terminada por caractere nulo de caracteres ANSI.

UnmanagedType.LPTStr (padrão)

Um ponteiro para uma matriz de terminada por caractere nulo de caracteres de dependente de plataforma.

UnmanagedType.LPWStr

Um ponteiro para uma matriz de caracteres Unicode terminada por caractere nulo.

UnmanagedType.TBStr

Um estilo COM BSTR com um comprimento prefixado e dependente de plataforma de caracteres.

VBByRefStr

Um valor que permite que o Visual Basic.NET para alterar uma seqüência de caracteres em código não gerenciado, e os resultados indicadas no código gerenciado. Esse valor é suportado somente para invocação de plataforma.

Esta tabela se aplica a seqüências de caracteres. No entanto, para StringBuilder, as únicas opções permitidas são LPStr, LPTStr, e LPWStr.

A definição de tipo a seguir mostra o uso correto de MarshalAsAttribute para a plataforma chamar chamadas.

Class StringLibAPI    
Public Declare Auto Sub PassLPStr Lib "StringLib.Dll" _
(<MarshalAs(UnmanagedType.LPStr)> s As String)    
Public Declare Auto Sub PassLPWStr Lib "StringLib.Dll" _
(<MarshalAs(UnmanagedType.LPWStr)> s As String)    
Public Declare Auto Sub PassLPTStr Lib "StringLib.Dll" _
(<MarshalAs(UnmanagedType.LPTStr)> s As String)    
Public Declare Auto Sub PassBStr Lib "StringLib.Dll" _
(<MarshalAs(UnmanagedType.BStr)> s As String)    
Public Declare Auto Sub PassAnsiBStr Lib "StringLib.Dll" _
(<MarshalAs(UnmanagedType.AnsiBStr)> s As String)    
Public Declare Auto Sub PassTBStr Lib "StringLib.Dll" _
(<MarshalAs(UnmanagedType.TBStr)> s As String)
End Class
class StringLibAPI {
[DllImport("StringLib.Dll")]
public static extern void PassLPStr([MarshalAs(UnmanagedType.LPStr)]
String s);
[DllImport("StringLib.Dll")]
public static extern void 
PassLPWStr([MarshalAs(UnmanagedType.LPWStr)]String s);
[DllImport("StringLib.Dll")]
public static extern void 
PassLPTStr([MarshalAs(UnmanagedType.LPTStr)]String s);
[DllImport("StringLib.Dll")]
public static extern void PassBStr([MarshalAs(UnmanagedType.BStr)]
String s);
[DllImport("StringLib.Dll")]
public static extern void 
PassAnsiBStr([MarshalAs(UnmanagedType.AnsiBStr)]String s);
[DllImport("StringLib.Dll")]
public static extern void PassTBStr([MarshalAs(UnmanagedType.TBStr)]
String s);
}

Seqüências de caracteres usadas em estruturas

Strings são membros válidos de estruturas; No entanto, StringBuilder buffers são inválidos em estruturas. A tabela a seguir mostra as opções de empacotamento para o tipo de dados de seqüência de caracteres quando o tipo é empacotado como um campo. O MarshalAsAttribute atributo fornece vários UnmanagedType valores de enumeração para empacotar strings para um campo.

Tipo de enumeração

Descrição do formato não gerenciado

UnmanagedType.BStr

Um estilo COM BSTR com um comprimento prefixado e todos os caracteres Unicode.

UnmanagedType.LPStr

Um ponteiro para uma matriz de terminada por caractere nulo de caracteres ANSI.

UnmanagedType.LPTStr

Um ponteiro para uma matriz de terminada por caractere nulo de caracteres de dependente de plataforma.

UnmanagedType.LPWStr

Um ponteiro para uma matriz de caracteres Unicode terminada por caractere nulo.

UnmanagedType.ByValTStr

Uma matriz de comprimento fixo de caracteres; tipo da matriz é determinado pelo conjunto de caracteres da estrutura que contém.

O ByValTStr tipo é usado para in-line, matrizes de caracteres de comprimento fixo, que aparecem dentro de uma estrutura. Outros tipos de aplicam referências de seqüência de caracteres contida em estruturas que contêm ponteiros para seqüências de caracteres.

O CharSet argumento o StructLayoutAttribute atributo que é aplicado à estrutura contendo determina o formato de caractere de seqüências de caracteres em estruturas. As estruturas de exemplo a seguir contêm referências de seqüência de caracteres e seqüências de caracteres embutida, bem como ANSI, Unicode e caracteres de dependente de plataforma.

Representação de biblioteca de tipo

struct StringInfoA {
   char *    f1;
   char      f2[256];
};
struct StringInfoW {
   WCHAR *   f1;
   WCHAR     f2[256];
   BSTR      f3;
};
struct StringInfoT {
   TCHAR *   f1;
   TCHAR     f2[256];
};

O exemplo de código a seguir mostra como usar o MarshalAsAttribute atributo para definir a mesma estrutura em formatos diferentes.

<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Ansi)> _
Structure StringInfoA
<MarshalAs(UnmanagedType.LPStr)> Public f1 As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
Public f2 As String
End Structure
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Unicode)> _
Structure StringInfoW
<MarshalAs(UnmanagedType.LPWStr)> Public f1 As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
Public f2 As String
<MarshalAs(UnmanagedType.BStr)> Public f3 As String
End Structure
<StructLayout(LayoutKind.Sequential, CharSet := CharSet.Auto)> _
Structure StringInfoT
<MarshalAs(UnmanagedType.LPTStr)> Public f1 As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst := 256)> _
Public f2 As String
End Structure
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct StringInfoA {
   [MarshalAs(UnmanagedType.LPStr)] public String f1;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public String f2;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
struct StringInfoW {
   [MarshalAs(UnmanagedType.LPWStr)] public String f1;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public String f2;
   [MarshalAs(UnmanagedType.BStr)] public String f3;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct StringInfoT {
   [MarshalAs(UnmanagedType.LPTStr)] public String f1;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public String f2;
}

Buffers de cadeia de caracteres de comprimento fixo

Em algumas circunstâncias, um buffer de caracteres de comprimento fixo deve ser passado para código não gerenciado para ser manipulado. Simplesmente passar uma seqüência de caracteres não funciona nesse caso porque o chamador não é possível modificar o conteúdo do buffer transmitido. Mesmo se a seqüência de caracteres é passada por referência, não é possível inicializar o buffer para um determinado tamanho.

A solução é passar um StringBuilder buffer como o argumento em vez de uma seqüência de caracteres. A StringBuilder pode ser a sua referência cancelada e modificado pelo receptor, desde que ela não excede a capacidade do StringBuilder. Também podem ser inicializado para um comprimento fixo. Por exemplo, se você inicializar um StringBuilder buffer para uma capacidade de N, o empacotador fornece um buffer de tamanho (N+ 1) caracteres. As contas de + 1 para o fato de que a seqüência de caracteres não gerenciada tem um terminador nulo, enquanto StringBuilder faz não.

Por exemplo, o Microsoft Win32 API GetWindowText função (definida no Windows. h) é um buffer de caracteres de comprimento fixo que deve ser passado para código não gerenciado para ser manipulado. LpStringaponta para um buffer alocado pelo chamador tamanho nMaxCount. O chamador deve alocar o buffer e definir o nMaxCount argumento para o tamanho do buffer alocado. O código a seguir mostra a GetWindowText declaração de função, conforme definido no Windows. h.

int GetWindowText(
HWND hWnd,        // Handle to window or control.
LPTStr lpString,  // Text buffer.
int nMaxCount     // Maximum number of characters to copy.
);

A StringBuilder pode ser a sua referência cancelada e modificado pelo receptor, desde que ela não excede a capacidade do StringBuilder. O exemplo de código a seguir demonstra como StringBuilder podem ser inicializados a um comprimento fixo.

Public Class Win32API
Public Declare Auto Sub GetWindowText Lib "User32.Dll" _
(h As Integer, s As StringBuilder, nMaxCount As Integer)
End Class
Public Class Window
   Friend h As Integer ' Friend handle to Window.
   Public Function GetText() As String
      Dim sb As New StringBuilder(256)
      Win32API.GetWindowText(h, sb, sb.Capacity + 1)
   Return sb.ToString()
   End Function
End Class
public class Win32API {
[DllImport("User32.Dll")]
public static extern void GetWindowText(int h, StringBuilder s, 
int nMaxCount);
}
public class Window {
   internal int h;        // Internal handle to Window.
   public String GetText() {
      StringBuilder sb = new StringBuilder(256);
      Win32API.GetWindowText(h, sb, sb.Capacity + 1);
   return sb.ToString();
   }
}

Consulte também

Conceitos

Blittable e tipos de não-Blittable

Atributos direcionais

Copiando e fixando

Outros recursos

Comportamento de empacotamento padrão