vb.net dllimport declare

DllImport vs Declare en VB.NET



(4)

Observo en la documentación de MSDN que hay varias formas de declarar una referencia a una función en una DLL externa desde un programa VB.NET.

Lo confuso es que MSDN afirma que solo puede usar la clase DllImportAttribute con prototipos de funciones compartidas " en casos excepcionales ", pero no pude encontrar la explicación para esta afirmación, mientras que simplemente puede usar la palabra clave Declare .

¿Por qué son diferentes y dónde usaré adecuadamente cada caso?


Aparentemente las declaraciones Declare y DllImport son básicamente las mismas. Puede usar el que prefiera.

A continuación se presenta una discusión de los pocos puntos que pueden funcionar de forma un poco diferente en cada uno, lo que puede influir en la preferencia por uno sobre el otro:

Comencé con un artículo de MSDN sobre Visual Studio 2003 titulado Using the DllImport Attribute . (Un poco viejo, pero dado que la declaración de DllImport parece haberse originado en .NET, me pareció apropiado volver al principio).

Dado un ejemplo de instrucción DllImport de:

[DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = Unicode)] int MessageBox(void* hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned int uType);

Dice que si se omite el valor de EntryPoint, el CLR buscará el nombre de la función (MessageBox, en este caso) como valor predeterminado. Sin embargo, en este caso, dado que se especificó un CharSet de Unicode, el CLR buscaría PRIMERO una función llamada "MessageBoxW" - la ''W'' indica un tipo de retorno Unicode. (La versión del tipo de retorno ANSI sería "MessageBoxA".) Si no se encontrara "MessageBoxW", ENTONCES el CLR buscaría una función API realmente llamada "MessageBox".

Los detalles actuales sobre la clase DllImportAttribute se pueden encontrar aquí, donde visualicé la versión de .NET Framework 4: DLLImportAttribute Class

Un comentario clave en la sección de Comentarios de esta página de .NET Framework 4 es que:

Aplica este atributo directamente a las definiciones de métodos C # y C ++; sin embargo, el compilador de Visual Basic emite este atributo cuando usa la instrucción Declare.

Entonces, al menos en lo que respecta a VB.NET, el compilador termina con una declaración Declare todos modos.

También hay una nota importante en esta página:

DllImportAttribute no admite la recopilación de tipos genéricos.

Entonces, parece que si quieres usar un tipo genérico, deberías usar una declaración Declare .

Luego, me dirigí a la información de declaración Declare. Una versión de Visual Studio 2010 (información de la declaración de Visual Basic) estaba aquí: declarar declaración

Un elemento clave aquí fue esta nota:

Puede usar Declare solo a nivel de módulo. Esto significa que el contexto de declaración para una referencia externa debe ser una clase, estructura o módulo, y no puede ser un archivo fuente, espacio de nombres, interfaz, procedimiento o bloque.

Aparentemente, si desea configurar una llamada API fuera de una clase, estructura o módulo, deberá usar la instrucción DllImport en lugar de Declare .

El ejemplo de declaración Declare en esta página es:

Declare Function getUserName Lib "advapi32.dll" Alias "GetUserNameA" ( ByVal lpBuffer As String, ByRef nSize As Integer) As Integer

Siguiendo ese ejemplo, está este pequeño bocado de información:

DllImportAttribute proporciona una forma alternativa de usar funciones en código no administrado. El siguiente ejemplo declara una función importada sin usar una declaración Declare.

seguido por, por supuesto, un ejemplo del uso de DllImport.

Con respecto a los resultados de Unicode vs ANSI, de acuerdo con esta página Declare, si especifica un valor de CharSet (disponible en Declare, pero no se muestra en el ejemplo anterior), CLR hará el mismo tipo de búsqueda de nombre automático que DllImport, ya sea para Unicode o ANSI.

Si no especifica un valor CharSet en la declaración Declare , entonces debe asegurarse de que el nombre de su función en el Declare sea igual al nombre de la función en el archivo de encabezado de la función API real, O debe especificar un valor Alias que coincida con el nombre de función real en el archivo de encabezado (como se muestra en el ejemplo anterior).

No pude encontrar ninguna documentación específica de Microsoft que indicara que DllImport o Declare fueran preferidos, o incluso recomendados, uno sobre el otro en cualquier situación que no sean las mencionadas anteriormente.

Mi conclusión, por lo tanto, es:

1) A menos que necesite colocar su definición en uno de los lugares en los que no se puede usar una declaración de declaración, cualquiera de las dos técnicas funcionará correctamente.

y

2) si está utilizando DllImport, asegúrese de especificar el valor CharSet que desea (Unicode o ANSI), o puede obtener resultados inesperados.


Declare es realmente un intento de mantener una sintaxis de P / Invoke que sería más familiar para los usuarios de Visual Basic 6.0 al convertir a VB.NET . Tiene muchas de las mismas características que P / Invoke, pero la clasificación de ciertos tipos, en particular las cadenas, son muy diferentes y pueden causar confusión a las personas más familiarizadas con las reglas de DllImport.

No estoy del todo seguro de a qué se refiere la documentación con la distinción "rara". Uso DllImport en mi código frecuentemente desde VB.NET y C # sin problema.

En general, usaría DllImport sobre Declare a menos que provenga de un fondo de Visual Basic 6.0. La documentación y las muestras para DllImport son mucho mejores y hay muchas herramientas destinadas a generar declaraciones DllImport.


Si necesita establecer una de las siguientes opciones, use el atributo DllImportAttribute ; de lo contrario, use Declare . Desde https://msdn.microsoft.com/en-us/library/w4byd5y4.aspx

Para aplicar los campos BestFitMapping, CallingConvention, ExactSpelling, PreserveSig, SetLastError o ThrowOnUnmappableChar a una declaración de Microsoft Visual Basic 2005, debe usar el atributo DllImportAttribute en lugar de la instrucción Declare.

No está claro a partir de la referencia anterior solo si esto se aplica solo a "Visual Basic 2005" o no, ya que la referencia anterior es de un artículo de .NET 4.5. Sin embargo, también encontré este artículo ( https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.110).aspx ) que es específico de la clase DllImportAttribute en. NET 4.5:

el compilador de Visual Basic emite este atributo cuando usa la declaración Declare. Para las definiciones de métodos complejos que incluyen los campos BestFitMapping, CallingConvention, ExactSpelling, PreserveSig, SetLastError o ThrowOnUnmappableChar, aplique este atributo directamente a las definiciones de métodos de Visual Basic .

Esto le indica que la opción Declare es azúcar sintáctico de VB.net que se convierte en DllImportAttribute en tiempo de compilación, y describe los escenarios exactos cuando se recomienda utilizar DllImportAttribute directamente.


En mi opinión, dado que esta palabra clave no se ve depreciada, etc. a partir de lo que busqué, simplemente use palabras clave en tiempo de compilación en lugar de atributos.

Además, cuando usa Declare , no necesita escribir la End Function . La ventaja de esto es que puede crear un módulo completo de declaraciones de funciones importadas línea por línea, sin necesidad de pulular su código con DllImport s y End Function s.

Cuando declara usar la palabra clave Declare , el compilador trata esta función como Shared todos modos, por lo que se puede acceder a través de otros objetos extenal.

Pero creo que en el actual VB.NET ambos están dirigidos al mismo objetivo y sin diferencia de rendimiento, no hay garantía en este caso.

Así que mi conclusión es: Use el Declare en lugar de DllImport , especialmente leyendo lo que citó que Microsoft afirmó que debería usarse en casos excepcionales.