OSInfo, exemple
Cet exemple montre comment passer soit une classe mise en forme par valeur, soit une structure par référence comme paramètre vers une fonction non managée qui s'attend à une structure avec une mémoire tampon de caractères incorporée.
L'exemple OSInfo utilise la fonction non managée suivante, illustrée avec sa déclaration de fonction d'origine :
GetVersionEx exportée à partir de Kernel32.dll.
// BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
La structure d'origine passée vers la fonction contient les éléments suivants :
typedef struct _OSVERSIONINFO
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
TCHAR szCSDVersion[ 128 ];
} OSVERSIONINFO;
Dans cet exemple, la classe OSVersionInfo et la structure OSVersionInfo2 génèrent les mêmes résultats lorsqu'elles sont passées vers la fonction non managée. L'attribut MarshalAsAttribute affecte à l'énumération UnmanagedType la valeur ByValTStr, qui est utilisée pour identifier les tableaux de caractères de longueur fixe inline qui apparaissent au sein des structures non managées.
La classe LibWrap contient deux prototypes : GetVersionEx passe la classe comme paramètre et GetVersionEx2 passe une structure comme paramètre. En appliquant explicitement les attributs InAttribute et OutAttribute, l'exemple s'assure que OSVersionInfo est marshalé comme paramètre en entrée/sortie et que l'appelant peut voir les changements remarshalés. (Pour de meilleures performances, l'attribut directionnel par défaut pour une classe est In, ce qui empêche l'appelant de voir les changements remarshalés.)
La structure OSVersionInfo2, qui est normalement passée par valeur, est déclarée avec le mot clé ref (ByRef en Visual Basic) et elle est passée par référence. La méthode Marshal.SizeOf détermine la taille, en octets, de la structure non managée.
Déclaration de prototypes
<StructLayout(LayoutKind.Sequential)> _
Public Class OSVersionInfo
Public OSVersionInfoSize As Integer
Public MajorVersion As Integer
Public MinorVersion As Integer
Public BuildNumber As Integer
Public PlatformId As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> _
Public CSDVersion As String
End Class
<StructLayout(LayoutKind.Sequential)> _
Public Structure OSVersionInfo2
Public OSVersionInfoSize As Integer
Public MajorVersion As Integer
Public MinorVersion As Integer
Public BuildNumber As Integer
Public PlatformId As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> _
Public CSDVersion As String
End Structure
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
[StructLayout(LayoutKind.Sequential)]
public class OSVersionInfo
{
public int OSVersionInfoSize;
public int MajorVersion;
public int MinorVersion;
public int BuildNumber;
public int PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public String CSDVersion;
}
[StructLayout(LayoutKind.Sequential)]
public struct OSVersionInfo2
{
public int OSVersionInfoSize;
public int MajorVersion;
public int MinorVersion;
public int BuildNumber;
public int PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public String CSDVersion;
}
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);
}
[StructLayout(LayoutKind::Sequential)]
public ref class OSVersionInfo
{
public:
int OSVersionInfoSize;
int MajorVersion;
int MinorVersion;
int BuildNumber;
int PlatformId;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst=128)]
String^ CSDVersion;
};
[StructLayout(LayoutKind::Sequential)]
public value struct OSVersionInfo2
{
public:
int OSVersionInfoSize;
int MajorVersion;
int MinorVersion;
int BuildNumber;
int PlatformId;
[MarshalAs(UnmanagedType::ByValTStr, SizeConst=128)]
String^ CSDVersion;
};
public ref class LibWrap
{
public:
[DllImport("kernel32")]
static bool GetVersionEx([In, Out] OSVersionInfo^ osvi);
[DllImport("kernel32", EntryPoint="GetVersionEx")]
static bool GetVersionEx2(OSVersionInfo2% osvi);
};
Fonctions d'appel
Public Class App
Public Shared Sub Main()
Console.WriteLine(vbNewLine + "Passing OSVersionInfo as a class")
Dim osvi As New OSVersionInfo()
osvi.OSVersionInfoSize = Marshal.SizeOf(osvi)
LibWrap.GetVersionEx(osvi)
Console.WriteLine("Class size: {0}", osvi.OSVersionInfoSize)
Console.WriteLine("OS Version: {0}.{1}", osvi.MajorVersion, osvi.MinorVersion)
Console.WriteLine(vbNewLine + "Passing OSVersionInfo2 as a struct")
Dim osvi2 As new OSVersionInfo2()
osvi2.OSVersionInfoSize = Marshal.SizeOf(osvi2)
LibWrap.GetVersionEx2(osvi2)
Console.WriteLine("Struct size: {0}", osvi2.OSVersionInfoSize)
Console.WriteLine("OS Version: {0}.{1}", osvi2.MajorVersion, osvi2.MinorVersion)
End Sub
End Class
public class App
{
public static void Main()
{
Console.WriteLine("\nPassing OSVersionInfo as a class");
OSVersionInfo osvi = new OSVersionInfo();
osvi.OSVersionInfoSize = Marshal.SizeOf(osvi);
LibWrap.GetVersionEx(osvi);
Console.WriteLine("Class size: {0}", osvi.OSVersionInfoSize);
Console.WriteLine("OS Version: {0}.{1}", osvi.MajorVersion, osvi.MinorVersion);
Console.WriteLine("\nPassing OSVersionInfo as a struct" );
OSVersionInfo2 osvi2 = new OSVersionInfo2();
osvi2.OSVersionInfoSize = Marshal.SizeOf(osvi2);
LibWrap.GetVersionEx2(ref osvi2);
Console.WriteLine("Struct size: {0}", osvi2.OSVersionInfoSize);
Console.WriteLine("OS Version: {0}.{1}", osvi2.MajorVersion, osvi2.MinorVersion);
}
}
public ref class App
{
public:
static void Main()
{
Console::WriteLine("\nPassing OSVersionInfo as a class");
OSVersionInfo^ osvi = gcnew OSVersionInfo();
osvi->OSVersionInfoSize = Marshal::SizeOf(osvi);
LibWrap::GetVersionEx(osvi);
Console::WriteLine("Class size: {0}", osvi->OSVersionInfoSize);
Console::WriteLine("OS Version: {0}.{1}", osvi->MajorVersion, osvi->MinorVersion);
Console::WriteLine("\nPassing OSVersionInfo as a struct" );
OSVersionInfo2 osvi2;
osvi2.OSVersionInfoSize = Marshal::SizeOf(osvi2);
LibWrap::GetVersionEx2(osvi2);
Console::WriteLine("Struct size: {0}", osvi2.OSVersionInfoSize);
Console::WriteLine("OS Version: {0}.{1}", osvi2.MajorVersion, osvi2.MinorVersion);
}
};
Voir aussi
Concepts
Types de données d'appel de code non managé
Marshaling par défaut pour les chaînes
Autres ressources
Creating Prototypes in Managed Code