Condividi tramite


Marshalling predefinito per le stringhe

Le classi System.String e System.StringBuilder hanno un comportamento di marshalling simile.

Il marshalling delle stringhe viene eseguito come tipo BSTR COM o come matrice di caratteri terminante in un riferimento null (Nothing in Visual Basic). È possibile eseguire il marshalling dei caratteri interni alla stringa come caratteri Unicode o ANSI oppure in un modo dipendente dalla piattaforma (Unicode su Microsoft Windows NT, Windows 2000 e Windows XP; ANSI su Windows 98 e Windows Millennium Edition).

In questo argomento sono disponibili le informazioni elencate di seguito sul marshalling dei tipi di stringhe:

  • Stringhe utilizzate nelle interfacce

  • Stringhe utilizzate nel richiamo piattaforma

  • Stringhe utilizzate nelle strutture

  • Buffer di stringhe a lunghezza fissa

Stringhe utilizzate nelle interfacce

Nella tabella riportata di seguito vengono mostrate le opzioni per il marshalling del tipo di dati stringa come argomento di metodo sul codice non gestito. L'attributo MarshalAsAttribute fornisce numerosi valori di enumerazione UnmanagedType per il marshalling di stringhe a interfacce COM.

Tipo di enumerazione Descrizione del formato non gestito

UnmanagedType.BStr  (impostazione predefinita)

BSTR di tipo COM con lunghezza con prefisso e caratteri Unicode.

UnmanagedType.LPStr

Puntatore a matrice con terminazione null di caratteri ANSI.

UnmanagedType.LPWStr

Puntatore a matrice con terminazione null di caratteri Unicode.

Nell'esempio riportato di seguito vengono mostrate le stringhe dichiarate nell'interfaccia IStringWorker.

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

Nell'esempio seguente viene mostrata l'interfaccia corrispondente descritta in una libreria dei tipi.

[…]
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);
);

Stringhe utilizzate nel richiamo piattaforma

Gli argomenti di stringa vengono copiati dal richiamo piattaforma mediante la conversione del formato di .NET Framework (Unicode) in quello non gestito della piattaforma. Le stringhe sono immutabili e non vengono ricopiate dalla memoria non gestita a quella gestita al termine della chiamata.

Nella tabella riportata di seguito sono elencate le opzioni per il marshalling delle stringhe come argomento del metodo di un richiamo piattaforma. L'attributo MarshalAsAttribute fornisce numerosi valori dell'enumerazione UnmanagedType per il marshalling di stringhe.

Tipo di enumerazione Descrizione del formato non gestito

UnmanagedType.AnsiBStr

BSTR di tipo COM con lunghezza con prefisso e caratteri ANSI.

UnmanagedType.BStr (impostazione predefinita)

BSTR di tipo COM con lunghezza con prefisso e caratteri Unicode.

UnmanagedType.LPStr

Puntatore a matrice con terminazione null di caratteri ANSI.

UnmanagedType.LPTStr

Puntatore a matrice con terminazione null di caratteri dipendenti dalla piattaforma.

UnmanagedType.LPWStr

Puntatore a matrice con terminazione null di caratteri Unicode.

UnmanagedType.TBStr

BSTR di tipo COM con lunghezza con prefisso e caratteri dipendenti dalla piattaforma.

Nella definizione dei tipi riportata di seguito viene mostrato l'uso corretto di MarshalAsAttribute per il richiamo piattaforma.

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

Stringhe utilizzate nelle strutture

Le stringhe sono membri validi di strutture, a differenza dei buffer di StringBuilder. Nella tabella riportata di seguito vengono elencate le opzioni per il marshalling del tipo di dati stringa come campo. L'attributo MarshalAsAttribute fornisce numerosi valori dell'enumerazione UnmanagedType per il marshalling di stringhe a un campo.

Tipo di enumerazione Descrizione del formato non gestito

UnmanagedType.BStr

BSTR di tipo COM con lunghezza con prefisso e caratteri Unicode.

UnmanagedType.LPStr

Puntatore a matrice con terminazione null di caratteri ANSI.

UnmanagedType.LPTStr

Puntatore a matrice con terminazione null di caratteri dipendenti dalla piattaforma.

UnmanagedType.LPWStr

Puntatore a matrice con terminazione null di caratteri Unicode.

UnmanagedType.ByValTStr

Matrice di caratteri a lunghezza fissa. Il tipo della matrice viene determinato dal set di caratteri della struttura contenitore.

Il tipo ByValTStr viene utilizzato per matrici di caratteri a lunghezza fissa inline presenti all'interno di una struttura. Gli altri tipi vengono applicati a riferimenti a stringhe all'interno di strutture contenenti puntatori a stringhe.

L'applicazione alla struttura contenitore dell'argomento CharSet dell'attributo StructLayoutAttribute consente di determinare il formato dei caratteri delle stringhe nelle strutture. Nelle strutture di esempio riportate di seguito sono contenuti riferimenti a stringhe e stringhe inline, nonché caratteri ANSI, Unicode e dipendenti dalla piattaforma.

Rappresentazione di libreria dei tipi

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

Nell'esempio di codice riportato di seguito viene mostrato come utilizzare l'attributo MarshalAsAttribute per definire la stessa struttura in diversi formati.

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

Buffer di stringhe a lunghezza fissa

In alcuni casi, è necessario passare un buffer di caratteri a lunghezza fissa nel codice non gestito da modificare. Il semplice passaggio di una stringa non funziona in questo caso perché il chiamato non può modificare il contenuto del buffer passato. Anche se la stringa viene passata per riferimento, non è possibile inizializzare il buffer su una dimensione specifica.

La soluzione consiste nel passare come argomento un buffer StringBuilder anziché una stringa. Il chiamato può annullare i riferimenti e modificare l'oggetto StringBuilder, purché non ne venga superata la capacità dell'oggetto StringBuilder stesso. È anche possibile inizializzare questo oggetto in base a una lunghezza fissa. Se, ad esempio, si inizializza un buffer StringBuilder su una capacità pari a N, un buffer di caratteri della dimensione (N+1) viene fornito dal gestore di marshalling. Il valore +1 tiene conto del fatto che, a differenza di StringBuilder, la stringa non gestita ha una terminazione null.

La funzione GetWindowText dell'API Microsoft Win32 (definita in Windows.h) rappresenta ad esempio un buffer di caratteri a lunghezza fissa che deve essere passato nel codice non gestito per essere modificato. LpString punta a un buffer allocato dal chiamante di dimensione nMaxCount. È previsto che il chiamante allochi il buffer e imposti l'argomento nMaxCount in base alla dimensione del buffer allocato. Nel codice riportato di seguito viene illustrata la dichiarazione della funzione GetWindowText come definita in Windows.h.

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

Il chiamato può annullare i riferimenti e modificare l'oggetto StringBuilder, purché non ne venga superata la capacità dell'oggetto StringBuilder stesso. Nell'esempio di codice riportato di seguito viene mostrato come inizializzare StringBuilder in base a una lunghezza fissa.

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

Vedere anche

Concetti

Tipi copiabili e non copiabili
Attributi direzionali
Copia e blocco

Altre risorse

Comportamento di marshalling predefinito