Buffers のサンプル
更新 : 2007 年 11 月
このサンプルでは、関数パラメータとして文字列 (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 型をマネージ文字列オブジェクトにコピーし、必要に応じて文字形式を拡張します。
次のコード例のソース コードは、.NET Framework「プラットフォーム呼び出しの技術サンプル」で提供されています。
プロトタイプの宣言
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 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 );
}
}