OSInfo のサンプル
更新 : 2007 年 11 月
このサンプルでは、1 つの埋め込み文字バッファを含む構造体を要求するアンマネージ関数に対して、フォーマットされたクラスを値渡しする方法、および構造体をパラメータとして参照渡しする方法を示します。
OSInfo のサンプルで使用するアンマネージ関数とその関数宣言を次に示します。
Kernel32.dll からエクスポートされる GetVersionEx
// BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
関数に渡された元の構造体には、次に示す要素が含まれています。
typedef struct _OSVERSIONINFO
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
TCHAR szCSDVersion[ 128 ];
} OSVERSIONINFO;
このサンプルでは、アンマネージ関数に渡された場合、OSVersionInfo クラスと OSVersionInfo2 構造体は同じ結果を生成します。MarshalAsAttribute 属性は UnmanagedType 列挙値に ByValTStr を設定します。これは、アンマネージ構造体に出現するインラインの固定長文字配列を識別するために使用されます。
LibWrap クラスには 2 つのプロトタイプが含まれます。GetVersionEx はパラメータとしてクラスを渡し、GetVersionEx2 はパラメータとして構造体を渡します。属性の InAttribute と OutAttribute を明示的に適用すると、このサンプルでは、OSVersionInfo が In/Out パラメータとしてマーシャリングされ、マーシャリングされた変更内容を呼び出し元が確実に参照できるようになります。パフォーマンスのためにクラスに関する既定の方向属性は In となります。このため、呼び出し元はマーシャリングされた変更内容を参照できません。
通常、値渡しされる OSVersionInfo2 構造体を、キーワード ref (Visual Basic では ByRef) によって宣言し、参照渡しを行います。Marshal.SizeOf メソッドは、アンマネージ構造体のサイズをバイト単位で確認します。
次のコード例のソース コードは、.NET Framework「プラットフォーム呼び出しの技術サンプル」で提供されています。
プロトタイプの宣言
< StructLayout( LayoutKind.Sequential )> _
Public Class OSVersionInfo
Public OSVersionInfoSize As Integer
…
< MarshalAs( UnmanagedType.ByValTStr, SizeConst := 128 )> _
Public versionString As String
End Class 'OSVersionInfo
< StructLayout( LayoutKind.Sequential )> _
Public Structure OSVersionInfo2
Public OSVersionInfoSize As Integer
…
< MarshalAs( UnmanagedType.ByValTStr, SizeConst := 128 )> _
Public versionString As String
End Structure 'OSVersionInfo2
Public Class LibWrap
Declare Ansi Function GetVersionEx Lib "kernel32" Alias _
"GetVersionExA" ( <[In], Out> ByVal osvi As OSVersionInfo ) As Boolean
Declare Ansi Function GetVersionEx2 Lib "kernel32" Alias _
"GetVersionExA" ( ByRef osvi As OSVersionInfo2 ) As Boolean
End Class 'LibWrap
[ StructLayout( LayoutKind.Sequential )]
public class OSVersionInfo
{
public int OSVersionInfoSize;
…
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]
public String versionString;
}
[ StructLayout( LayoutKind.Sequential )]
public struct OSVersionInfo2
{
public int OSVersionInfoSize;
…
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]
public String versionString;
}
public class LibWrap
{
[ DllImport( "kernel32" )]
public static extern bool GetVersionEx( [In, Out] OSVersionInfo osvi );
[ DllImport( "kernel32", EntryPoint="GetVersionEx" )]
public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi );
}
関数の呼び出し
Public Class App
Public Shared Sub Main()
Console.WriteLine( ControlChars.CrLf + "Passing OSVersionInfo _
as class" )
Dim osvi As New OSVersionInfo()
osvi.OSVersionInfoSize = Marshal.SizeOf( osvi )
LibWrap.GetVersionEx( osvi )
Console.WriteLine( "Class size: {0}", osvi.OSVersionInfoSize )
…
Console.WriteLine( ControlChars.CrLf + "Passing OSVersionInfo _
as struct" )
Dim osvi2 As New OSVersionInfo2()
osvi2.OSVersionInfoSize = Marshal.SizeOf( osvi2 )
LibWrap.GetVersionEx2( osvi2 )
Console.WriteLine( "Struct size: {0}", osvi2.OSVersionInfoSize )
…
End Sub 'Main
End Class 'App
public class App
{
public static void Main()
{
Console.WriteLine( "\nPassing OSVersionInfo as class" );
OSVersionInfo osvi = new OSVersionInfo();
osvi.OSVersionInfoSize = Marshal.SizeOf( osvi );
LibWrap.GetVersionEx( osvi );
Console.WriteLine( "Class size: {0}", osvi.OSVersionInfoSize );
…
Console.WriteLine( "\nPassing OSVersionInfo as struct" );
OSVersionInfo2 osvi2 = new OSVersionInfo2();
osvi2.OSVersionInfoSize = Marshal.SizeOf( osvi2 );
LibWrap.GetVersionEx2( ref osvi2 );
Console.WriteLine( "Struct size: {0}", osvi2.OSVersionInfoSize );
…
}
}