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