Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este ejemplo se muestra cómo llamar a una función no administrada que espera recibir un puntero a una estructura que contiene una cadena. Además, se muestra cómo utilizar una clase administrada para representar una estructura no administrada, cómo aplicar los atributos InAttribute y OutAttribute para calcular la referencia de la clase y devolverla al llamador, y cómo declarar e inicializar diferentes campos de la clase para producir la representación no administrada correcta.
En el ejemplo OpenFileDlg se utiliza la siguiente función no administrada, que se muestra con su declaración de función original:
GetOpenFileName exportada desde Comdlg32.dll.
BOOL GetOpenFileName(LPOPENFILENAME lpofn);
La estructura LPOPENFILENAME de la API Win32, que se pasa a la función anterior, contiene los elementos siguientes:
typedef struct tagOFN {
DWORD lStructSize;
//…
LPCTSTR lpstrFilter;
//…
LPTSTR lpstrFile;
DWORD nMaxFile;
LPTSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCTSTR lpstrInitialDir;
LPCTSTR lpstrTitle;
//…
LPCTSTR lpstrDefExt;
//…
} OPENFILENAME, *LPOPENFILENAME;
En este ejemplo, la clase OpenFileName contiene los elementos de la estructura original como miembros de clase. La estructura no administrada se declara como una clase, en lugar de como una estructura administrada, para mostrar cómo se puede utilizar una clase cuando la función no administrada espera recibir un puntero a una estructura. Como una clase administrada es un tipo de referencia, cuando se pasa por valor, al código no administrado se pasa un puntero a la clase. Eso es precisamente lo que la función no administrada espera recibir.
El atributo StructLayoutAttribute se aplica a la clase para garantizar que los miembros se organizan en la memoria de forma secuencial, en el orden en que aparecen. El campo CharSet está configurado de forma que la invocación de plataforma pueda elegir entre los formatos ANSI y Unicode en tiempo de ejecución, en función de la plataforma de destino.
La clase LibWrap contiene el prototipo administrado del método GetOpenFileName, que pasa la clase OpenFileName como un parámetro In/Out. Al aplicar InAttribute y OutAttribute de forma explícita, en el ejemplo se garantiza que se calcula una referencia de OpenFileName 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 clase App crea una nueva instancia de la clase OpenFileName y utiliza el método Marshal.SizeOf para determinar el tamaño, en bytes, de la estructura no administrada.
El código fuente de los ejemplos de código siguientes lo proporciona el Ejemplo de tecnología de invocación de plataformas de .NET Framework.
Declaración de prototipos
' Declare a class member for each structure element.
< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Auto )> _
Public Class OpenFileName
Public structSize As Integer = 0
'…
Public filter As String = Nothing
'…
Public file As String = Nothing
Public maxFile As Integer = 0
Public fileTitle As String = Nothing
Public maxFileTitle As Integer = 0
Public initialDir As String = Nothing
Public title As String = Nothing
'…
Public defExt As String = Nothing
'…
End Class 'OpenFileName
Public Class LibWrap
' Declare managed prototype for the unmanaged function.
Declare Auto Function GetOpenFileName Lib "Comdlg32.dll" ( _
<[In], Out> ByVal ofn As OpenFileName ) As Boolean
End Class 'LibWrap
// Declare a class member for each structure element.
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Auto )]
public class OpenFileName
{
public int structSize = 0;
//…
public String filter = null;
//…
public String file = null;
public int maxFile = 0;
public String fileTitle = null;
public int maxFileTitle = 0;
public String initialDir = null;
public String title = null;
//…
public String defExt = null;
//…
}
public class LibWrap
{
// Declare a managed prototype for the unmanaged function.
[ DllImport( "Comdlg32.dll", CharSet=CharSet.Auto )]
public static extern bool GetOpenFileName([ In, Out ]
OpenFileName ofn );
}
Llamadas a funciones
Public Class App
Public Shared Sub Main()
Dim ofn As New OpenFileName()
ofn.structSize = Marshal.SizeOf( ofn )
ofn.filter = "Log files" & ChrW(0) & "*.log" & ChrW(0) & _
"Batch files" & ChrW(0) & "*.bat" & ChrW(0)
ofn.file = New String( New Char( 256 ) {})
ofn.maxFile = ofn.file.Length
ofn.fileTitle = New String( New Char( 64 ) {})
ofn.maxFileTitle = ofn.fileTitle.Length
ofn.initialDir = "C:\"
ofn.title = "Open file called using platform invoke..."
ofn.defExt = "txt"
If LibWrap.GetOpenFileName( ofn ) Then
Console.WriteLine( "Selected file with full path: {0}", _
ofn.file )
End If
End Sub 'Main
End Class 'OpenFileDlgSample
public class App
{
public static void Main()
{
OpenFileName ofn = new OpenFileName();
ofn.structSize = Marshal.SizeOf( ofn );
ofn.filter = "Log files\0*.log\0Batch files\0*.bat\0";
ofn.file = new String( new char[ 256 ]);
ofn.maxFile = ofn.file.Length;
ofn.fileTitle = new String( new char[ 64 ]);
ofn.maxFileTitle = ofn.fileTitle.Length;
ofn.initialDir = "C:\\";
ofn.title = "Open file called using platform invoke...";
ofn.defExt = "txt";
if( LibWrap.GetOpenFileName( ofn ))
{
Console.WriteLine( "Selected file with full path: {0}",
ofn.file );
}
}
}
Vea también
Tareas
Ejemplo de tecnología de invocación de plataformas
Conceptos
Calcular referencias de cadenas
Tipos de datos de invocación de plataforma
Cálculo de referencias predeterminado para cadenas
Crear prototipos en código administrado