Поделиться через


Пример OSInfo

Обновлен: Ноябрь 2007

В этом примере показан способ передачи в неуправляемую функцию в качестве параметра форматированного класса по значению или структуры по ссылке. Неуправляемая функция ожидает структуру с встроенным символьным буфером.

В примере OSInfo используются следующие неуправляемые функции, показанные со своим исходным объявлением.

  • Функция GetVersionEx, экспортированная из Kernel32.dll.

    // 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 содержит два прототипа: GetVersionEx передает класс в качестве параметра, а GetVersionEx2 передает структуру в качестве параметра. Применив явно атрибуты InAttribute и OutAttribute, можно убедиться, что класс OSVersionInfo маршалируется как параметр In/Out, и вызывающий объект может отследить изменения, маршалируемые обратно. (Для повышения производительности атрибутом направления по умолчанию является In, что не позволяет вызывающему объекту отслеживать изменения, маршалируемые обратно.)

Структура OSVersionInfo2, которая обычно передается по значению, объявляется с помощью зарезервированного слова ref (ByRef в Visual Basic) и передается по ссылке. Метод 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 );
      …     
   }
}

См. также

Задачи

Пример технологии вызова неуправляемого кода

Основные понятия

Маршалинг строк

Типы данных вызовов неуправляемого кода

Маршалинг по умолчанию для строк

Создание прототипов в управляемом коде