VB.NET 中的 DllImport 与声明
我注意到 MSDN 文档中有多种方法来声明引用从 VB.NET 程序中调用外部 DLL 中的函数。
令人困惑的是,MSDN 声称您只能使用 具有共享函数原型的 DllImportAttribute 类“在极少数情况下” ,但我找不到此语句的解释,而您可以简单地使用 而是使用 Declare
关键字。
为什么这些不同,我应该在哪里适当地使用每种情况?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
显然 Declare 和 DllImport 语句基本相同。 您可以使用您喜欢的任何一个。
以下是对每个要点的讨论,这些要点的工作方式可能略有不同,这可能会影响对其中一个的偏好:
我从 MSDN 上一篇关于 Visual Studio 2003 的文章开始,标题为 使用 DllImport 属性。 (有点旧,但由于 DllImport 语句似乎起源于 .NET,因此回到开头似乎是合适的。)
给出一个示例 DllImport 语句:
它表示如果省略 EntryPoint 值,则 CLR 将查找函数名称(在本例中为 MessageBox)作为默认名称。 然而,在本例中,由于指定了 Unicode CharSet,CLR 将首先查找名为“MessageBoxW”的函数 - “W”表示 Unicode 返回类型。 (ANSI 返回类型版本将为“MessageBoxA”。)如果未找到“MessageBoxW”,则 CLR 将查找实际称为“MessageBox”的 API 函数。
有关 DllImportAttribute 类的当前详细信息可以在此处找到,我在其中查看了 .NET Framework 4 版本:DLLImportAttribute Class
此 .NET Framework 4 页面的“备注”部分中的关键注释是:
因此,在 VB.NET 中,使用
Declare
语句会导致编译器生成DLLImportAttribute
。此页面还有一个重要注释:
因此,如果您想使用泛型类型,则必须使用
Declare
语句。接下来,我前往 Declare 声明信息。 Visual Studio 2010 版本(Visual Basic 语句信息)位于:声明声明
这里的一个关键项目是这个注释:
显然,如果您想在类、结构或模块之外设置 API 调用,则必须使用 DllImport 语句而不是
Declare
。此页面上的示例
Declare
语句如下:在该示例之后是一些小信息:
当然,接下来是 DllImport 用法的示例。
关于 Unicode 与 ANSI 结果,根据此 Declare 页面,如果指定 CharSet 值(在 Declare 中可用,但在上面的示例中未显示),CLR 将执行与 DllImport 相同类型的自动名称搜索 - 对于 Unicode 或ANSI。
如果您没有在
Declare
语句中指定 CharSet 值,那么您必须确保 Declare 中的函数名称与实际 API 函数头文件中的函数名称相同,或者您必须指定与头文件中的实际函数名称匹配的Alias
值(如上例所示)。我找不到任何具体的 Microsoft 文档说明在除上述情况之外的任何情况下,DllImport 或 Declare 是首选的,甚至是推荐的。
因此,我的结论是:
Declare
语句的地方,否则任何一种技术都可以正常工作,并且
Apparently the Declare and DllImport statements are basically the same. You can use whichever you prefer.
Following is a discussion of the few points that may work a little differently in each, which may influence a preference for one over the other:
I started with an article from MSDN regarding Visual Studio 2003 titled Using the DllImport Attribute. (A bit old, but since the DllImport statement seems to have originated in .NET, it seemed appropriate to go back to the beginning.)
Given an example DllImport statement of:
It says that if the EntryPoint value is left out, the CLR will look for the name of the function (MessageBox, in this case) as a default. However, in this instance, since a CharSet of Unicode was specified, the CLR would FIRST look for a function called "MessageBoxW" - the 'W' indicating a Unicode return type. (The ANSI return type version would be "MessageBoxA".) If no "MessageBoxW" were found, THEN the CLR would look for an API function actually called "MessageBox".
Current specifics about the DllImportAttribute class can be found here, where I viewed the .NET Framework 4 version: DLLImportAttribute Class
A key comment in the Remarks section of this .NET Framework 4 page is that:
So, in VB.NET, using the
Declare
statement causes the compiler to generate aDLLImportAttribute
.There is also an important note in this page:
So, it would appear that if you want to use a generic type, you'd have to use a
Declare
statement.Next, I headed to the Declare statement information. A Visual Studio 2010 version (Visual Basic statement info) was here: Declare Statement
A key item here was this note:
Apparently, if you want to set up an API call outside of a class, structure, or module, you'll have to use the DllImport statement instead of the
Declare
.The example
Declare
statement on this page is:Following that example is this little tidbit of information:
followed by, of course, an example of DllImport usage.
Regarding Unicode vs ANSI results, according to this Declare page, if you specify a CharSet value (available in Declare, but not shown in the example above) the CLR will do the same type of automatic name search that DllImport does - for either Unicode or ANSI.
If you do not specify a CharSet value in the
Declare
statement, then you must make sure that your function name in the Declare is the same as the function name in the actual API function's header file, OR you must specifiy anAlias
value that matches the actual function name in the header file (as shown in the example above).I was not able to find any specific Microsoft documentation stating that either DllImport or Declare were preferred, or even recommended, over one another in any situation other than those noted above.
My conclusion, therefore, is:
Declare
statement cannot be used, either technique will work fine,and
Declare 实际上是维护 Visual Basic 6.0 更熟悉的 P/Invoke 语法的尝试用户转换为 VB.NET。 它具有许多与 P/Invoke 相同的功能,但某些类型(特别是字符串)的编组非常不同,可能会给更熟悉 DllImport 规则的人带来一些混乱。
我不完全确定文档中提到的“罕见”区别是什么。 我经常在 VB.NET 和 C# 代码中使用 DllImport,没有出现任何问题。
一般来说,我会使用 DllImport 而不是 Declare,除非您有 Visual Basic 6.0 背景。 DllImport 的文档和示例要好得多,并且有许多旨在生成 DllImport 声明的工具。
Declare is really an attempt to maintain a P/Invoke syntax which would be more familiar to Visual Basic 6.0 users converting to VB.NET. It has many of the same features as P/Invoke but the marshalling of certain types, in particular strings, are very different and can cause a bit of confusion to people more familiar with DllImport rules.
I'm not entirely sure what the documentation is alluding to with the "rare" distinction. I use DllImport in my code frequently from both VB.NET and C# without issue.
In general, I would use DllImport over Declare unless you come from a Visual Basic 6.0 background. The documentation and samples for DllImport are much better and there are many tools aimed at generating DllImport declarations.
在我看来,由于从我搜索的内容来看,这个关键字看起来并没有被弃用,因此只需使用编译时关键字而不是属性。
另外,当您使用
Declare
时,您不需要编写End Function
。 这样做的优点是,您可以逐行创建函数导入声明的整个模块,而无需使用DllImport
和End Function
来填充代码。当您使用
Declare
关键字进行声明时,编译器无论如何都会将此函数视为Shared
,因此可以通过其他外部对象访问它。但我认为在当前的 VB.NET 中,它们都针对相同的目标,并且没有性能差异 - 对此没有任何保证。
所以我的结论是:请使用 Declare 而不是 DllImport,尤其是阅读您引用的内容 微软表示应该在极少数情况下使用它。
In my opinion, since this keyword doesn't look deprected, etc. from what I searched, simply use compile-time keywords rather than attributes.
Also, when you use the
Declare
, you don't need to write theEnd Function
. The advantage of that is that you can create a whole module of declarations of function imports line by line, with no need to pulute your code withDllImport
s andEnd Function
s.When you declare using the
Declare
keyword, the compiler treats this function asShared
anyway, so it can be accessed via other extenal objects.But I think in the current VB.NET they're both addressed to the same target and no performance difference - no warranty on this one.
So my conclusion is: Do use the Declare instead of DllImport, especially reading what you quoted that Microsoft stated that it should be used in rare cases.
如果您需要设置以下选项之一,请使用
DllImportAttribute
属性,否则使用Declare
。 来自 https://msdn.microsoft.com/en-us/library/w4byd5y4。 ASPX仅从上述参考文献中尚不清楚这是否仅适用于“Visual Basic 2005”,因为上述参考文献来自 .NET 4.5 文章。 但是,我还找到了这篇文章(https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.110).aspx ),这是特定于
DllImportAttribute 类:
这告诉您
Declare
选项是 VB.net 语法糖,它在编译时转换为DllImportAttribute
,并概述了使用DllImportAttribute
时的确切场景> 直接推荐。If you need to set one of the following options, then use
DllImportAttribute
attribute, else useDeclare
. From https://msdn.microsoft.com/en-us/library/w4byd5y4.aspxIt is unclear from the above reference only whether this applies to only "Visual Basic 2005" or not, as the above reference is from a .NET 4.5 article. However, I also found this article (https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.110).aspx ) which is specific to the
DllImportAttribute
class in .NET 4.5 :This tells you that the
Declare
option is VB.net syntactical sugar which is converted toDllImportAttribute
at compile time, and outlines the exact scenarios when usingDllImportAttribute
directly is recommended.