Esempio di OSInfo
Aggiornamento: novembre 2007
In questo esempio viene dimostrato come passare una classe formattata per valore o una struttura per riferimento come parametro a una funzione non gestita per la quale è prevista una struttura con un buffer di caratteri incorporato.
Nell'esempio di OSInfo viene utilizzata la seguente funzione non gestita, illustrata con la dichiarazione di funzione originale:
GetVersionEx esportata da Kernel32.dll.
// BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
La struttura originale passata alla funzione contiene i seguenti elementi:
typedef struct _OSVERSIONINFO
{
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
TCHAR szCSDVersion[ 128 ];
} OSVERSIONINFO;
In questo esempio, la classe OSVersionInfo e la struttura OSVersionInfo2 producono gli stessi risultati quando vengono passate alla funzione non gestita. Il valore dell'enumerazione UnmanagedType viene impostato dall'attributo MarshalAsAttribute su ByValTStr, che consente di identificare la matrice di caratteri inline a lunghezza fissa presente nella struttura non gestita.
La classe LibWrap contiene due prototipi: GetVersionEx passa la classe come parametro e GetVersionEx2 passa una struttura come parametro. Mediante l'applicazione esplicita degli attributi InAttribute e OutAttribute, nell'esempio vengono garantiti il marshalling di OSVersionInfo come parametro in/out e la visualizzazione delle modifiche restituite con il marshalling da parte del chiamante. Per questioni di prestazioni, l'attributo direzionale predefinito per una classe è In, condizione che impedisce al chiamante di vedere le modifiche restituite con il marshalling.
La struttura OSVersionInfo2, che viene in genere passata per valore, è dichiarata con la parola chiave ref (ByRef in Visual Basic) e viene passata per riferimento. Il metodo Marshal.SizeOf consente di determinare la dimensione in byte della struttura non gestita.
Il codice sorgente per gli esempi di codice riportati di seguito è fornito dall'Esempio di tecnologia di richiamo piattaforma di .NET Framework.
Dichiarazione dei prototipi
< 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 );
}
Chiamata delle funzioni
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 );
…
}
}
Vedere anche
Attività
Esempio di tecnologia di richiamo piattaforma
Concetti
Tipi di dati del richiamo piattaforma