Mik*_*ike 15 vb.net dllimport declare
我在MSDN文档中注意到有多种方法可以在VB.NET程序中声明对外部DLL中函数的引用.
令人困惑的是,MSDN声称你只能在极少数情况下使用DllImportAttribute类和共享函数原型,但是我找不到这个语句的解释,而你可以简单地使用关键字.Declare
为什么这些不同,我会在哪里适当地使用每个案例?
lea*_*nne 19
显然,Declare和DllImport语句基本相同.您可以使用您喜欢的任何一种.
以下是对可能在每种方面略有不同的几点的讨论,这可能会影响对一方的偏好:
我从MSDN上关于Visual Studio 2003的一篇题为" 使用DllImport属性 "的文章开始.(有点旧,但由于DllImport语句似乎起源于.NET,所以回到开头似乎是合适的.)
给出一个示例DllImport语句:
[DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = Unicode)]
int MessageBox(void* hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned int uType);
Run Code Online (Sandbox Code Playgroud)
它表示如果遗漏了EntryPoint值,CLR将查找函数的名称(在本例中为MessageBox)作为默认值.但是,在这种情况下,由于指定了Unicode的CharSet,因此CLR将首先查找名为"MessageBoxW"的函数 - 表示Unicode返回类型的"W".(ANSI返回类型版本将是"MessageBoxA".)如果没有找到"MessageBoxW",那么CLR将寻找实际上称为"MessageBox"的API函数.
关于DllImportAttribute类的当前细节可以在这里找到,我查看了.NET Framework 4版本:DLLImportAttribute类
此.NET Framework 4页面的"备注"部分中的关键注释是:
您可以将此属性直接应用于C#和C++方法定义; 但是,当您使用Declare语句时,Visual Basic编译器会发出此属性.
因此,至少与VB.NET相关,编译器最终会以Declare语句结束.
此页面中还有一个重要说明:
DllImportAttribute不支持泛型类型的编组.
所以,看起来如果你想使用泛型类型,你必须使用一个Declare语句.
接下来,我前往Declare声明信息.Visual Studio 2010版本(Visual Basic语句信息)位于此处:声明语句
这里的一个关键项目是这个说明:
您只能在模块级别使用Declare.这意味着外部引用的声明上下文必须是类,结构或模块,并且不能是源文件,命名空间,接口,过程或块.
显然,如果要在类,结构或模块之外设置API调用,则必须使用DllImport语句而不是Declare.
Declare此页面上的示例语句为:
Declare Function getUserName Lib "advapi32.dll" Alias "GetUserNameA" (
ByVal lpBuffer As String, ByRef nSize As Integer) As Integer
Run Code Online (Sandbox Code Playgroud)
在这个例子之后是这个小小的信息:
DllImportAttribute提供了在非托管代码中使用函数的替代方法.以下示例在不使用Declare语句的情况下声明导入的函数.
当然,后面是DllImport用法的一个例子.
关于Unicode与ANSI结果,根据此Declare页面,如果指定CharSet值(在Declare中可用,但未在上面的示例中显示),CLR将执行与DllImport相同类型的自动名称搜索 - 对于Unicode或ANSI.
如果未在Declare语句中指定CharSet值,则必须确保Declare中的函数名与实际API函数头文件中的函数名相同,或者必须指定Alias与实际函数匹配的值头文件中的名称(如上例所示).
我无法找到任何特定的Microsoft文档,声明在上述情况之外的任何情况下,DllImport或Declare都是首选的,甚至是推荐的.
因此,我的结论是:
1)除非你需要将你的定义放在其中一个地方Declare不能使用一个声明,否则这两种技术都可以正常工作,
和
2)如果您正在使用DllImport,请确保指定所需的CharSet值(Unicode或ANSI),否则可能会出现意外结果.
Jar*_*Par 12
声明实际上是一种维护P/Invoke语法的尝试,对于转换为VB.NET的 Visual Basic 6.0用户来说,这种语法更为熟悉.它具有许多与P/Invoke相同的功能,但是某些类型的编组,特别是字符串,是非常不同的,并且可能对更熟悉DllImport规则的人造成一些混淆.
我不完全确定文档是用"罕见"的区别来暗示的.我经常在VB.NET和C#的代码中使用DllImport而没有问题.
一般情况下,我会使用DllImport over Declare,除非你来自Visual Basic 6.0背景.DllImport的文档和示例要好得多,并且有许多工具旨在生成DllImport声明.
在我看来,由于这个关键字看起来并不像我搜索的那样,所以只需使用编译时关键字而不是属性.
另外,当你使用时Declare,你不需要写End Function.这样做的好处是你可以逐行创建一个函数导入声明的整个模块,而不需要用DllImports和End Functions 来代码.
当您声明使用Declare关键字时,编译器Shared无论如何都会将此函数视为处理,因此可以通过其他外部对象访问它.
但我认为在当前的VB.NET中,它们都是针对同一目标而没有性能差异 - 对此没有保证.
所以我的结论是:使用Declare而不是DllImport,特别是阅读你引用的内容,微软声称它应该在极少数情况下使用.