VB.NET 中的 DllImport 与声明
其他提示
显然 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);
它表示如果省略 EntryPoint 值,则 CLR 将查找函数名称(在本例中为 MessageBox)作为默认名称。然而,在本例中,由于指定了 Unicode CharSet,CLR 将首先查找名为“MessageBoxW”的函数 - “W”表示 Unicode 返回类型。(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
在这个例子之后是这个小信息:
DllImportAttribute 提供了在非托管代码中使用函数的另一种方法。以下示例不使用 Declare 语句来声明导入函数。
当然,接下来是 DllImport 用法的示例。
关于 Unicode 与 ANSI 结果,根据此 Declare 页面,如果指定 CharSet 值(在 Declare 中可用,但在上面的示例中未显示),CLR 将执行与 DllImport 相同类型的自动名称搜索 - 对于 Unicode 或ANSI。
如果您未在中指定 CharSet 值 Declare
声明,那么您必须确保 Declare 中的函数名称与实际 API 函数头文件中的函数名称相同,或者您必须指定一个 Alias
与头文件中的实际函数名称匹配的值(如上例所示)。
我找不到任何具体的 Microsoft 文档说明在除上述情况之外的任何情况下,DllImport 或 Declare 是首选的,甚至是推荐的。
因此,我的结论是:
1) 除非您需要将定义放在以下位置之一 Declare
不能使用语句,任何一种技术都可以正常工作,
和
2) 如果您使用 DllImport,请确保指定所需的 CharSet 值(Unicode 或 ANSI),否则可能会得到意外结果。
在我看来,因为这个关键字看起来不deprected等从我搜索,只需使用编译时的关键字,而不是属性。
此外,当您使用Declare
,你不需要写End Function
。那的好处是,你可以创建线功能的进口线的声明的整个模块,而无需与DllImport
s和End Function
s到pulute你的代码。
当的声明使用Declare
关键字,则编译器将这个函数为反正Shared
,所以它可以通过其它extenal对象进行访问。
但我认为,在目前的VB.NET他们都发往同一目标,并且没有性能上的差异 - 在这一个没有保修
所以我的结论是:不要使用声明以代替的DllImport ,尤其是阅读你所引述的微软指出,它应该在罕见的情况下被使用。
如果您需要设置以下选项之一,请使用 DllImportAttribute
属性,否则使用 Declare
. 。从 https://msdn.microsoft.com/en-us/library/w4byd5y4.aspx
要将BestFitMapping,呼叫范围,精确播放,Preservesig,SetlasterRor或ThrowOnunMappableChar字段应用于Microsoft Visual Basic 2005声明,您必须使用dllimportAttribute属性而不是声明语句。
仅从上述参考文献中尚不清楚这是否仅适用于“Visual Basic 2005”,因为上述参考文献来自 .NET 4.5 文章。不过我还发现了这篇文章(https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.110).aspx )这是特定于 DllImportAttribute
.NET 4.5 中的类:
当您使用声明语句时,Visual Basic编译器会发出此属性。 对于包括BestFitMapping,呼叫范围,精确播放,Preservesig,SetlasterRor或ThrowOnunMappableChar字段的复杂方法定义,您将此属性直接应用于Visual Basical Basical方法定义.
这告诉您, Declare
选项是 VB.net 语法糖,转换为 DllImportAttribute
在编译时,并概述了使用时的确切场景 DllImportAttribute
直接推荐。