Freigeben über


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

Marshallen von Zeichenfolgen

Datentypen für den Plattformaufruf

Standardmäßiges Marshalling für Zeichenfolgen

Weitere Ressourcen

Creating Prototypes in Managed Code