Zeichenfolgenbeispiel
Dieses Beispiel demonstriert die Verwendung einer aus einer nicht verwalteten Funktion zurückgegebenen Zeichenfolge und deren Übergabe an eine Struktur, die eine Zeichenfolge im Unicode- bzw. ANSI-Format enthält. Es wird gezeigt, wie diese Zeichenfolgen ordnungsgemäß initialisiert und die zurückgegebenen Werte abgerufen werden.
Das Beispiel für Zeichenfolgen verwendet die folgenden nicht verwalteten Funktionen, die jeweils zusammen mit ihrer ursprünglichen Funktionsdeklaration aufgeführt werden:
TestStringAsResult aus PinvokeLib.dll exportiert.
char* TestStringAsResult();
TestStringInStruct aus PinvokeLib.dll exportiert.
void TestStringInStruct(MYSTRSTRUCT* pStruct);
TestStringInStructAnsi aus PinvokeLib.dll exportiert.
void TestStringInStructAnsi(MYSTRSTRUCT2* pStruct);
PinvokeLib.dll ist eine benutzerdefinierte, nicht verwaltete Bibliothek, die Implementierungen für die zuvor aufgelisteten Funktionen und zwei Strukturen (MYSTRSTRUCT und MYSTRSTRUCT2) enthält Diese Strukturen enthalten die folgenden Elemente:
typedef struct _MYSTRSTRUCT
{
wchar_t* buffer;
UINT size;
} MYSTRSTRUCT;
typedef struct _MYSTRSTRUCT2
{
char* buffer;
UINT size;
} MYSTRSTRUCT2;
In diesem Beispiel enthalten die verwaltete MyStrStruct-Struktur und die verwaltete MyStrStruct2-Struktur verwaltete Zeichenfolgen anstelle von StringBuilder-Puffern, da der Typ StringBuilder nicht innerhalb einer Struktur verwendet werden kann. Das StructLayoutAttribute-Attribut ist so eingerichtet, dass sichergestellt wird, dass die Member im Speicher sequenziell in der Reihenfolge ihres Erscheinens angeordnet sind. Das CharSet-Feld ist so eingerichtet, dass das ANSI-Format bzw. das Unicode-Format angegeben wird.
Die LibWrap-Klasse enthält die durch die App-Klasse aufgerufenen verwalteten Prototypmethoden. Obwohl Strukturen in der Regel durch einen Wert übergeben werden, sind die Argumente für die TestStringInStruct-Methode und die TestStringInStructAnsi-Methode durch das ref-Schlüsselwort (ByRef in Visual Basic) markiert, das Strukturen durch einen Verweis übergibt.
Deklarieren von Prototypen
' 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);
};
Aufrufen von Funktionen
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);
}
};
Siehe auch
Konzepte
Datentypen für den Plattformaufruf
Standardmäßiges Marshalling für Zeichenfolgen
Weitere Ressourcen
Creating Prototypes in Managed Code