Compartir a través de


Ejemplo OSInfo

En este ejemplo se demuestra cómo pasar una clase con formato por valor o una estructura por referencia como parámetro a una función no administrada que espera recibir una estructura con un búfer de caracteres incrustado.

En el ejemplo OSInfo se utiliza la siguiente función no administrada, que se muestra con su declaración de función original:

  • GetVersionEx exportada desde Kernel32.dll.

    // BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo);
    

La estructura original pasada a la función contiene los elementos siguientes:

typedef struct _OSVERSIONINFO
{ 
  DWORD dwOSVersionInfoSize; 
  DWORD dwMajorVersion; 
  DWORD dwMinorVersion; 
  DWORD dwBuildNumber; 
  DWORD dwPlatformId; 
  TCHAR szCSDVersion[ 128 ]; 
} OSVERSIONINFO; 

En este ejemplo, la clase OSVersionInfo y la estructura OSVersionInfo2 producen el mismo resultado cuando se pasan a la función no administrada. El atributo MarshalAsAttribute establece el valor de la enumeración UnmanagedType en ByValTStr, que se utiliza para identificar la matriz de caracteres de longitud fija insertada que aparece en la estructura no administrada.

La clase LibWrap contiene dos prototipos: GetVersionEx pasa la clase como parámetro y GetVersionEx2 pasa una estructura como parámetro. Al aplicar los atributos InAttribute y OutAttribute de forma explícita, en el ejemplo se asegura que se calcula una referencia de OSVersionInfo como un parámetro In/Out y el llamador puede ver los cambios del cálculo. Por razones de rendimiento, el atributo direccional de una clase es In, lo que impide que el llamador vea los cambios del cálculo.

La estructura OSVersionInfo2, que se suele pasar por valor, se declara con la palabra clave ref (ByRef en Visual Basic) y se pasa por referencia. El método Marshal.SizeOf determina el tamaño de la estructura no administrada, en bytes.

Declaración de prototipos

<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);
};

Llamadas a funciones

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);
    }
};

Vea también

Conceptos

Calcular referencias de cadenas

Tipos de datos de invocación de plataforma

Cálculo de referencias predeterminado para cadenas

Otros recursos

Creating Prototypes in Managed Code