Pregunta

Me he dado cuenta en la documentación de MSDN que no están múltiples maneras a declarar una referencia a una función en una DLL externa desde un programa VB.NET.

Lo confuso es que MSDN afirma que sólo se puede utilizar el clase DllImportAttribute con prototipos de funciones compartidas" en casos raros "pero no pude encontrar la explicación de esta afirmación, mientras que sólo tiene que utilizar el Declare palabra clave en su lugar.

¿Por qué estos diferentes, y donde iba a utilizar adecuadamente cada caso?

¿Fue útil?

Solución

Declarar es en realidad un intento de mantener un P / Invoke sintaxis que sería más familiar visual Basic 6.0 los usuarios se convierten al VB.NET . Tiene muchas de las mismas características que P / Invoke pero el ordenamiento de ciertos tipos, en las cadenas particular, son muy diferentes y puede causar un poco de confusión a las personas más familiarizadas con las reglas DllImport.

No estoy del todo seguro de lo que la documentación está aludiendo a la distinción "raro". Yo uso DllImport en mi código con frecuencia tanto de VB.NET y C # sin problema.

En general, me gustaría utilizar DllImport sobre Declarar menos que usted viene de un fondo de Visual Basic 6.0. La documentación y muestras para DllImport son mucho mejores y hay muchas herramientas destinadas a generar declaraciones DllImport.

Otros consejos

Al parecer, las instrucciones Declare y DllImport son básicamente los mismos. Puede utilizar lo que usted prefiera.

La siguiente es una discusión de los pocos puntos que puede funcionar un poco diferente en cada uno, que pueden influir en una preferencia por una sobre la otra:

Empecé con un artículo de MSDN Visual Studio 2003 con respecto Uso la DllImport Atributo . (Un poco viejo, pero desde la declaración DllImport parece haberse originado en .NET, parecía apropiado para ir de nuevo al principio.)

Con un ejemplo de declaración DllImport:

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

Se dice que si el valor EntryPoint se deja fuera, el CLR buscará el nombre de la función (MessageBox , en este caso) como un defecto. Sin embargo, en este caso, desde que se especifica un juego de caracteres Unicode, el CLR en primer lugar buscar una función llamada "MessageBoxW" - la 'W' que indica un tipo de retorno Unicode. (La versión ANSI tipo de retorno sería "MessageBoxA".) Si no se encuentran "MessageBoxW", entonces el CLR buscaría una función API realidad llamado "cuadro de mensaje".

detalles actuales acerca de la clase DllImportAttribute se pueden encontrar aquí, donde vi la versión de .NET Framework 4: DllImportAttribute Clase

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

  

aplicar este atributo directamente a C # y C ++ definiciones de métodos; Sin embargo, el compilador de Visual Basic emite este atributo cuando se utiliza la instrucción Declare.

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

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

  

El DllImportAttribute no admite el cálculo de referencias de tipos genéricos.

Por lo tanto, parecería que si desea utilizar un tipo genérico, que tendría que utilizar una declaración Declare.

A continuación, se dirigió a la información de instrucción Declare. Una versión de Visual Studio 2010 (Visual información instrucción básica) era aquí: DECLARE

Un elemento clave en este caso era esta nota:

  

Puede utilizar Declarar sólo 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 de origen, espacio de nombres, interfaz, procedimiento o bloque.

Al parecer, si desea establecer una llamada a la API fuera de una clase, estructura o módulo, que tendrá que utilizar la instrucción DllImport en lugar de la Declare.

La declaración Declare ejemplo de 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 es esta golosina poco de información:

  

El DllImportAttribute proporciona una forma alternativa de utilizar las funciones de código no administrado. En el siguiente ejemplo se declara una función importada sin necesidad de utilizar una instrucción Declare.

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

En cuanto a Unicode vs resultados ANSI, de acuerdo a esta página Declarar, si se especifica un valor CharSet (disponible en la declaración, sino que no se muestra en el ejemplo anterior) el CLR va a hacer el mismo tipo de búsqueda de nombre automático que DllImport hace - para Unicode o ANSI.

Si no se especifica un valor CharSet en la declaración Declare, entonces debe asegurarse de que su nombre de función en la declare es el mismo que el nombre de la función en el archivo de cabecera de la función API actual, o debe specifiy un valor Alias que coincide con el nombre de la función real en el archivo de cabecera (como se muestra en el ejemplo anterior).

Yo no era capaz de encontrar ninguna documentación de Microsoft específica que indica que, o bien DllImport o declarar fueron preferidos, o incluso recomienda, una sobre la otra en una situación distinta de las indicadas anteriormente.

Mi conclusión, por tanto, es:

1) A menos que se han de fijar su definición en uno de los lugares Declare una declaración no puede ser utilizado, ya sea técnica funcionará bien,

y

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

En mi opinión, ya que esta palabra clave no tiene un aspecto deprected, etc por lo que he buscado, sólo tiene que utilizar en tiempo de compilación en lugar de palabras clave atributos.

Además, cuando se utiliza el Declare, no es necesario escribir el End Function. La ventaja de esto es que se puede crear un módulo completo de las declaraciones de las importaciones de función línea por línea, sin necesidad de pulute el código con DllImports y End Functions.

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

Sin embargo, creo que en el actual VB.NET los dos están dirigidas al mismo objetivo y no hay diferencia de rendimiento -. No garantiza en este caso

Así que mi conclusión es: Foro de utilizar la declare en lugar de DllImport , especialmente la lectura de lo que usted ha citado Microsoft declaró que se debe utilizar en casos excepcionales.

Si es necesario configurar una de las siguientes opciones, a continuación, utilizar el atributo DllImportAttribute, el uso Declare otra cosa. De https://msdn.microsoft.com/en-us/library/w4byd5y4. aspx

  

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

No está claro a partir de la referencia anterior sólo si esto se aplica sólo a "Visual Basic 2005" o no, según 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 para la clase DllImportAttribute en .NET 4.5 :

  

el compilador de Visual Basic emite este atributo cuando se utiliza el   declaración declarar. Para definiciones de métodos complejos que incluyen   BestFitMapping, CallingConvention, ExactSpelling, PreserveSig,   SetLastError o ThrowOnUnmappableChar campos, que se aplican este   atribuir directamente a definiciones de métodos de Visual Basic .

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top