Buffers のサンプル
このサンプルでは、関数パラメーターとして文字列 (LPSTR) を要求するアンマネージ関数に対し、In/Out パラメーターとして文字列を渡す方法を示します。 さらに、その文字列に割り当てられたメモリを呼び出し元が解放できない特別なケースにおいて、アンマネージ メソッドから返された文字列を使用する方法も示します。
このサンプル プラットフォームは、Kernel32.dll からエクスポートされた 2 つのネイティブ Win32 関数を呼び出します。
GetSystemDirectory
システム ディレクトリのパスを取得します。
GetCommandLine
現在のプロセスのコマンド ライン文字列を取得します。
LibWrap クラスには、コンソール アプリケーションの Main から呼び出されるアンマネージ関数のマネージ プロトタイプが含まれています。 対象プラットフォームに従って、プラットフォーム呼び出しが実行時に ANSI 形式と Unicode 形式のどちらかを選択できるように、CharSet フィールドを設定します。 このフィールドの詳細については、「文字セットの指定」を参照してください。
GetSystemDirectory プロトタイプ メソッドは、アンマネージ LPSTR 型の代わりに、StringBuilder バッファーを使用します。 バッファーのサイズは固定されたままです。 元の関数の要件を満たすために、GetSystemDirectory はバッファー サイズ変数を 2 番目の引数として渡します。 文字列ではなく StringBuilder バッファーによって、宣言内の LPTSTR 型が置換されます。 変更不可の文字列とは異なり、StringBuilder バッファーは変更可能です。
ネイティブ GetCommandLine 関数は、オペレーティング システムが割り当てて所有する、バッファーへのポインターを返します。 戻り値の型として文字列をマーシャリングする場合、相互運用マーシャラーは、関数から返された元の LPTSTR 型が指すメモリを解放する必要があると見なします。 このメモリがマーシャラーによって自動的にクリアされるのを回避するために、マネージ GetCommandLine プロトタイプは文字列の代わりに IntPtr 型を返します。 PtrToStringAuto メソッドはアンマネージ LPSTR 型をマネージ文字列オブジェクトにコピーし、必要に応じて文字形式を拡張します。
プロトタイプの宣言
Public Class LibWrap
Declare Auto Sub GetSystemDirectory Lib "Kernel32.dll" _
(ByVal sysDirBuffer As StringBuilder, ByVal buffSize As Integer)
Declare Auto Function GetCommandLine Lib "Kernel32.dll" () As IntPtr
End Class
public class LibWrap
{
[DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
public static extern int GetSystemDirectory(StringBuilder
sysDirBuffer, int size);
[DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr GetCommandLine();
}
public ref class LibWrap
{
public:
[DllImport("Kernel32.dll", CharSet=CharSet::Auto)]
static int GetSystemDirectory(StringBuilder^
sysDirBuffer, int size);
[DllImport("Kernel32.dll", CharSet=CharSet::Auto)]
static IntPtr GetCommandLine();
};
関数の呼び出し
Public Class App
Public Shared Sub Main()
' Call GetSystemDirectory.
Dim sysDirBuffer As New StringBuilder(256)
LibWrap.GetSystemDirectory(sysDirBuffer, sysDirBuffer.Capacity)
' ...
' Call GetCommandLine.
Dim cmdLineStr As IntPtr = LibWrap.GetCommandLine()
Dim commandLine As String = Marshal.PtrToStringAuto(cmdLineStr)
End Sub
End Class
public class App
{
public static void Main()
{
// Call GetSystemDirectory.
StringBuilder sysDirBuffer = new StringBuilder(256);
LibWrap.GetSystemDirectory(sysDirBuffer, sysDirBuffer.Capacity);
// ...
// Call GetCommandLine.
IntPtr cmdLineStr = LibWrap.GetCommandLine();
string commandLine = Marshal.PtrToStringAuto(cmdLineStr);
}
}
public ref class App
{
public:
static void Main()
{
// Call GetSystemDirectory.
StringBuilder^ sysDirBuffer = gcnew StringBuilder(256);
LibWrap::GetSystemDirectory(sysDirBuffer, sysDirBuffer->Capacity);
// ...
// Call GetCommandLine.
IntPtr cmdLineStr = LibWrap::GetCommandLine();
String^ commandLine = Marshal::PtrToStringAuto(cmdLineStr);
}
};
参照
概念
その他の技術情報
Creating Prototypes in Managed Code