Пример строк
Обновлен: Ноябрь 2007
В этом примере показано использование строки, которая возвращается неуправляемой функцией, а также способ передачи структуры, содержащей строку в формате Юникода или ANSI. Также показаны способ инициализации этих строк и способ получения возвращаемых значений.
В этом примере используются следующие неуправляемые функции, показанные со своим исходным объявлением.
Функция TestStringAsResult, экспортированная из PinvokeLib.dll.
char* TestStringAsResult();
Функция TestStringInStruct, экспортированная из PinvokeLib.dll.
void TestStringInStruct(MYSTRSTRUCT* pStruct);
Функция TestStringInStructAnsi, экспортированная из PinvokeLib.dll.
void TestStringInStructAnsi(MYSTRSTRUCT2* pStruct);
PinvokeLib.dll — это пользовательская неуправляемая библиотека, содержащая реализации ранее описанных функций и две структуры, MYSTRSTRUCT и MYSTRSTRUCT2. Эти структуры содержат следующие элементы:
typedef struct _MYSTRSTRUCT
{
wchar_t* buffer;
UINT size;
} MYSTRSTRUCT;
typedef struct _MYSTRSTRUCT2
{
char* buffer;
UINT size;
} MYSTRSTRUCT2;
В этом примере управляемые структуры MyStrStruct and MyStrStruct2 содержат управляемые строки вместо буферов StringBuilder, так как тип StringBuilder нельзя использовать внутри структуры. Атрибут StructLayoutAttribute задается, чтобы гарантировать последовательный порядок членов в памяти, соответствующий порядку их появления. Значение поля CharSet определяет формат ANSI или Юникод.
Класс LibWrap содержит управляемые прототипы методов, вызываемых классом App. Хотя структуры обычно передаются по значению, аргументы методов TestStringInStruct и TestStringInStructAnsi содержат ключевое слово ref (ByRef в Visual Basic), позволяющее передавать структуры по ссылке.
Исходный код для следующих примеров кода см. в разделе Пример технологии вызова неуправляемого кода для .NET Framework.
Объявление прототипов
' 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 'MyStrStruct
< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Ansi )> _
Public Structure MyStrStruct2
Public buffer As String
Public size As Integer
End Structure 'MyStrStruct2
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 'LibWrap
// 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 );
}
Вызов функций
Public Class App
Public Shared Sub Main()
' String as result.
Dim strng As String = LibWrap.TestStringAsResult()
Console.WriteLine( ControlChars.CrLf + "String returned: {0}", _
strng )
' 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( "*"c, buffer.Capacity - 8)
Dim mss As MyStrStruct
mss.buffer = buffer.ToString()
mss.size = mss.buffer.Length
LibWrap.TestStringInStruct( mss )
Console.WriteLine( ControlChars.CrLf + _
"Buffer after Unicode function call: {0}", mss.buffer )
Dim buffer2 As New StringBuilder( "content", 100 )
buffer2.Append( ChrW(0) )
buffer2.Append( "*"c, buffer2.Capacity - 8 )
Dim mss2 As MyStrStruct2
mss2.buffer = buffer2.ToString()
mss2.size = mss2.buffer.Length
LibWrap.TestStringInStructAnsi( mss2 )
Console.WriteLine( ControlChars.CrLf + _
"Buffer after Ansi function call: {0}", mss2.buffer )
End Sub 'Main
End Class 'App
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 );
}
}
См. также
Задачи
Пример технологии вызова неуправляемого кода
Основные понятия
Типы данных вызовов неуправляемого кода