Strings 샘플
이 샘플에서는 관리되지 않는 함수에서 반환된 문자열을 사용하는 방법과 유니코드 형식 또는 ANSI 형식의 문자열이 포함된 구조체를 전달하는 방법을 보여 줍니다. 또한, 이러한 문자열을 올바르게 초기화하는 방법과 반환된 값을 검색하는 방법을 보여 줍니다.
String 샘플에서는 다음의 관리되지 않는 함수를 사용합니다. 이 함수들은 원래의 함수 선언과 함께 표시되어 있습니다.
PinvokeLib.dll에서 내보낸 TestStringAsResult
char* TestStringAsResult();
PinvokeLib.dll에서 내보낸 TestStringInStruct
void TestStringInStruct(MYSTRSTRUCT* pStruct);
PinvokeLib.dll에서 내보낸 TestStringInStructAnsi
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;
이 샘플에서는 관리되는 StringBuilder 형식이 구조체 내에서 사용될 수 없기 때문에 MyStrStruct 및 MyStrStruct2 구조체에는 StringBuilder 버퍼 대신 관리되는 문자열이 포함되어 있습니다. 멤버가 나타나는 순서에 따라 메모리에 순차적으로 정렬되도록 StructLayoutAttribute 특성이 설정됩니다. CharSet 필드는 ANSI 또는 유니코드 형식을 지정하도록 설정됩니다.
LibWrap 클래스에는 App 클래스에서 호출하는 관리되는 프로토타입 메서드가 포함되어 있습니다. 구조체는 일반적으로 값으로 전달되지만 TestStringInStruct 및 TestStringInStructAnsi 메서드에 대한 인수는 구조체를 참조로 전달하는 ref(Visual Basic에서 ByRef) 키워드로 표시됩니다.
프로토타입 선언
' 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);
};
함수 호출
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);
}
};
참고 항목
개념
기타 리소스
Creating Prototypes in Managed Code