我注意到 MSDN 文档中有 多种方式 从 VB.NET 程序中声明对外部 DLL 中函数的引用。

令人困惑的是 MSDN 声称你只能使用 Dll导入属性 具有共享函数原型的类”在极少数情况下”,但我找不到这个语句的解释,而你可以简单地使用 Declare 关键字代替。

为什么这些不同,我应该在哪里适当地使用每种情况?

有帮助吗?

解决方案

声明是真正保持 P /调用语法这将是对更熟悉的尝试Visual Basic 6.0的用户转换到 VB.NET 。它有许多相同的功能,为P / Invoke的,但某些类型的编组,特别是字符串,是非常不同的,可能造成一些混乱的人更熟悉的DllImport规则。

我不完全知道什么是文档暗指用“罕见”的区别。我在我的代码中使用的DllImport经常来自VB.NET和C#没有问题。

在一般情况下,我会使用的DllImport了声明,除非你来自一个Visual Basic 6.0的背景。的文档和的DllImport样品好得多,有旨在产生的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。那的好处是,你可以创建线功能的进口线的声明的整个模块,而无需与DllImports和End Functions到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 直接推荐。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top