Esempio di stringhe
In questo esempio viene dimostrato come utilizzare una stringa restituita da una funzione non gestita e come passare una struttura che contiene una stringa formattata con Unicode o con ANSI. Viene mostrato come inizializzare correttamente queste stringhe e come recuperare i valori restituiti.
Nell'esempio di stringa vengono utilizzate le seguenti funzioni non gestite, illustrate con le dichiarazioni di funzione originali:
TestStringAsResult esportata da PinvokeLib.dll.
char* TestStringAsResult();
TestStringInStruct esportata da PinvokeLib.dll.
void TestStringInStruct(MYSTRSTRUCT* pStruct);
TestStringInStructAnsi esportata da PinvokeLib.dll.
void TestStringInStructAnsi(MYSTRSTRUCT2* pStruct);
PinvokeLib.dll è una libreria non gestita personalizzata contenente implementazioni per le funzioni elencate in precedenza e due strutture, MYSTRSTRUCT e MYSTRSTRUCT2, le quali contengono i seguenti elementi:
typedef struct _MYSTRSTRUCT
{
wchar_t* buffer;
UINT size;
} MYSTRSTRUCT;
typedef struct _MYSTRSTRUCT2
{
char* buffer;
UINT size;
} MYSTRSTRUCT2;
In questo esempio le strutture gestite MyStrStruct e MyStrStruct2 contengono stringhe gestite anziché buffer StringBuilder, poiché il tipo StringBuilder non può essere utilizzato all'interno di una struttura. L'attributo StructLayoutAttribute viene impostato in modo che i membri vengano disposti in sequenza nella memoria, nell'ordine in cui appaiono. Il campo CharSet viene impostato in modo da specificare il formato ANSI o Unicode.
La classe LibWrap contiene i metodi di prototipo gestiti chiamati dalla classe App. Sebbene le strutture vengano in genere passate per valore, gli argomenti per i metodi TestStringInStruct e TestStringInStructAnsi sono contrassegnati con la parola chiave ref (ByRef in Visual Basic), tramite la quale le strutture vengono passate per riferimento.
Dichiarazione dei prototipi
' 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
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Public Structure MyStrStruct2
Public buffer As String
Public size As Integer
End Structure
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
// 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);
}
// Declares a managed structure for each unmanaged structure.
[StructLayout(LayoutKind::Sequential, CharSet=CharSet::Unicode)]
public value struct MyStrStruct
{
public:
String^ buffer;
int size;
};
[StructLayout(LayoutKind::Sequential, CharSet=CharSet::Ansi)]
public value struct MyStrStruct2
{
public:
String^ buffer;
int size;
};
public ref class LibWrap
{
public:
// Declares managed prototypes for unmanaged functions.
[DllImport("..\\LIB\\PinvokeLib.dll")]
static String^ TestStringAsResult();
[DllImport("..\\LIB\\PinvokeLib.dll")]
static void TestStringInStruct(MyStrStruct% mss);
[DllImport("..\\LIB\\PinvokeLib.dll")]
static void TestStringInStructAnsi(MyStrStruct2% mss);
};
Chiamata delle funzioni
Public Class App
Public Shared Sub Main()
' String as result.
Dim str As String = LibWrap.TestStringAsResult()
Console.WriteLine(vbNewLine + "String returned: {0}", str)
' 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("*", buffer.Capacity - 8)
Dim mss As MyStrStruct
mss.buffer = buffer.ToString()
mss.size = mss.buffer.Length
LibWrap.TestStringInStruct(mss)
Console.WriteLine(vbNewLine + "Buffer after Unicode function call: {0}", _
mss.buffer )
Dim buffer2 As New StringBuilder("content", 100)
buffer2.Append(ChrW(0))
buffer2.Append("*", buffer2.Capacity - 8)
Dim mss2 As MyStrStruct2
mss2.buffer = buffer2.ToString()
mss2.size = mss2.buffer.Length
LibWrap.TestStringInStructAnsi(mss2)
Console.WriteLine(vbNewLine + "Buffer after Ansi function call: {0}", mss2.buffer)
End Sub
End Class
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);
}
}
public ref 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 = gcnew 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(mss);
Console::WriteLine( "\nBuffer after Unicode function call: {0}",
mss.buffer );
StringBuilder^ buffer2 = gcnew 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(mss2);
Console::WriteLine("\nBuffer after Ansi function call: {0}",
mss2.buffer);
}
};
Vedere anche
Concetti
Tipi di dati di platform invoke
Marshalling predefinito per le stringhe
Altre risorse
Creating Prototypes in Managed Code