Compartilhar via


Exemplo de seqüências de caracteres

Este exemplo demonstra como usar uma seqüência de caracteres retornada de uma função não gerenciada e como passar uma estrutura que contém uma seqüência de caracteres formatada em Unicode ou ANSI-formatado. Ele mostra como inicializar corretamente essas seqüências de caracteres e como recuperar os valores retornados.

O exemplo de seqüência de caracteres usa as seguintes funções não gerenciadas, mostradas com sua declaração de função original:

  • TestStringAsResult exportados do PinvokeLib.dll.

    char* TestStringAsResult();
    
  • TestStringInStruct exportados do PinvokeLib.dll.

    void TestStringInStruct(MYSTRSTRUCT* pStruct);
    
  • TestStringInStructAnsi exportados do PinvokeLib.dll.

    void TestStringInStructAnsi(MYSTRSTRUCT2* pStruct);
    

PinvokeLib.dll é uma biblioteca de não gerenciada personalizada que contém implementações para as funções listadas anteriormente e duas estruturas, MYSTRSTRUCT e MYSTRSTRUCT2. Essas estruturas de contenham os seguintes elementos:

typedef struct _MYSTRSTRUCT
{
   wchar_t* buffer;
   UINT size; 
} MYSTRSTRUCT;
typedef struct _MYSTRSTRUCT2
{
   char* buffer;
   UINT size; 
} MYSTRSTRUCT2;

Neste exemplo, o gerenciado MyStrStruct e MyStrStruct2 estruturas contêm seqüências gerenciadas em vez de StringBuilder buffers porque a StringBuilder tipo não pode ser usado dentro de uma estrutura. O StructLayoutAttribute atributo está definido para garantir que os membros são organizados na memória seqüencialmente, na ordem em que aparecem. O CharSet campo será definido para especificar o ANSI ou Unicode formatos.

O LibWrap classe contém os métodos de protótipo gerenciado chamados pelo App classe. Embora as estruturas normalmente são passadas por valor, os argumentos para o TestStringInStruct e TestStringInStructAnsi métodos são marcados com o ref (ByRef em Visual Basic) palavra-chave, estruturas de passa por referência.

A declaração de protótipos

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

Chamando funções

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

Consulte também

Conceitos

Empacotamento de Strings

Tipos de dados de invocação de plataforma

Padrão de empacotamento de Strings

Outros recursos

Creating Prototypes in Managed Code