声明对外部文件中实现的过程的引用。
语法
[ <attributelist> ] [ accessmodifier ] [ Shadows ] [ Overloads ] _
Declare [ charsetmodifier ] [ Sub ] name Lib "libname" _
[ Alias "aliasname" ] [ ([ parameterlist ]) ]
' -or-
[ <attributelist> ] [ accessmodifier ] [ Shadows ] [ Overloads ] _
Declare [ charsetmodifier ] [ Function ] name Lib "libname" _
[ Alias "aliasname" ] [ ([ parameterlist ]) ] [ As returntype ]
部件
术语 | 定义 |
---|---|
attributelist |
可选。 请参阅 属性列表。 |
accessmodifier |
可选。 可以是以下值之一: - 公共 - 保护 - 朋友 - 私人 - 受保护的好友 - 专用保护 请参阅 Visual Basic 中的 Access 级别。 |
Shadows |
可选。 查看 阴影。 |
charsetmodifier |
可选。 指定字符集和文件搜索信息。 可以是以下值之一: - Ansi (默认值) - Unicode - 自动 |
Sub |
可选,但 Sub 必须显示或 Function 必须显示。 指示外部过程不返回值。 |
Function |
可选,但 Sub 必须显示或 Function 必须显示。 指示外部过程返回一个值。 |
name |
必填。 此外部引用的名称。 有关详细信息,请参阅 声明的元素名称。 |
Lib |
必填。 引入一个 Lib 子句,该子句标识包含外部过程的外部文件(DLL 或代码资源)。 |
libname |
必填。 包含声明过程的文件的名称。 |
Alias |
可选。 指示所声明的过程不能按中指定的 name 名称在其文件中标识。 在 . 中 aliasname 指定其标识。 |
aliasname |
如果使用关键字, Alias 则为必需。 以以下两种方式之一标识过程的字符串:过程在其文件中的入口点名称,引号 ( "" )-或- 数字符号( # )后跟一个整数,指定过程入口点在其文件中的序号 |
parameterlist |
如果过程采用参数,则为必需。 请参阅 参数列表。 |
returntype |
如果 Function 指定且 Option Strict 为 On .,则为必需项。 过程返回的值的数据类型。 |
注解
有时,需要在项目外部调用文件(如 DLL 或代码资源)中定义的过程。 执行此作时,Visual Basic 编译器无权正确调用过程所需的信息,例如过程所在的位置、标识过程的方式、调用序列和返回类型以及它使用的字符串字符集。 该 Declare
语句创建对外部过程的引用,并提供此必要信息。
只能在模块级别使用 Declare
。 这意味着外部引用的 声明上下文 必须是类、结构或模块,不能是源文件、命名空间、接口、过程或块。 有关详细信息,请参阅 声明上下文和默认访问级别。
外部引用默认为 公共 访问。 可以使用访问修饰符调整其访问级别。
规则
特性。 可以将属性应用于外部引用。 应用的任何属性仅在项目中生效,而不适用于外部文件。
修饰 符。 外部过程是隐式 共享的。 声明外部引用时无法使用
Shared
关键字,也不能更改其共享状态。外部过程不能参与重写、实现接口成员或处理事件。 因此,不能在语句中使用
Overrides
Declare
、Overridable
、NotOverridable
、MustOverride
Implements
或Handles
关键字。外部过程名称。 不必为此外部引用提供与其外部文件 (in) 中的过程入口点名称相同的名称(
aliasname
inname
)。 可以使用子Alias
句指定入口点名称。 如果外部过程的名称与 Visual Basic 保留修饰符或变量、过程或同一范围内的任何其他编程元素同名,这非常有用。注释
大多数 DLL 中的入口点名称区分大小写。
外部过程编号。 或者,可以使用子
Alias
句指定外部文件的导出表中入口点的序号。 为此,请从数字符号(#
)开始aliasname
。 如果 Visual Basic 中不允许外部过程名称中的任何字符,或者外部文件导出不带名称的过程,这非常有用。
数据类型规则
参数数据类型。
On
如果是Option Strict
,则必须指定每个参数的parameterlist
数据类型。 这可以是任何数据类型或枚举、结构、类或接口的名称。 在内parameterlist
,使用子As
句指定要传递给每个参数的参数的数据类型。注释
如果未为 .NET Framework 编写外部过程,则必须注意数据类型是否对应。 例如,如果使用参数(Visual Basic 6.0 中的 16 位)声明对 Visual Basic 6.0 过程
Integer
的外部引用,则必须像在Declare
语句中一样Short
标识相应的参数,因为这是 Visual Basic 中的 16 位整数类型。 同样,Long
Visual Basic 6.0 中的数据宽度不同,并且Date
以不同的方式实现。返回数据类型。 如果外部过程是且
Function
Option Strict
是On
,则必须指定返回给调用代码的值的数据类型。 这可以是任何数据类型或枚举、结构、类或接口的名称。注释
Visual Basic 编译器不验证数据类型是否与外部过程的数据类型兼容。 如果不匹配,公共语言运行时会在运行时生成 MarshalDirectiveException 异常。
默认数据类型。 如果
Option Strict
为Off
且未指定参数parameterlist
的数据类型,则 Visual Basic 编译器会将相应的参数转换为 对象数据类型。 同样,如果未指定returntype
,编译器将返回数据类型设置为Object
。注释
由于你正在处理可能已在不同的平台上编写的外部过程,因此对数据类型做出任何假设或允许它们默认是危险的。 指定每个参数和返回值的数据类型(如果有)更安全。 这也提高了代码的可读性。
行为
范围。 外部引用在其类、结构或模块范围内。
一生。 外部引用的生存期与声明它的类、结构或模块的生存期相同。
调用外部过程。 调用外部过程的方式与调用
Function
某个或Sub
过程的方式相同,方法是在表达式中使用它(如果它返回一个值),或者通过在 Call 语句 中指定它(如果它不返回值)。将参数传递到与语句中指定的
Declare
完全一样parameterlist
的外部过程。 不要考虑最初在外部文件中声明参数的方式。 同样,如果有返回值,请完全按照语句中指定的Declare
方式returntype
使用它。字符集。 可以在调用外部过程时指定
charsetmodifier
Visual Basic 应如何封送字符串。Ansi
修饰符指示 Visual Basic 将所有字符串封送至 ANSI 值,修饰Unicode
符将它定向为将所有字符串封送给 Unicode 值。Auto
修饰符指示 Visual Basic 根据基于外部引用name
aliasname
或指定时根据 .NET Framework 规则封送字符串。 默认值是Ansi
。charsetmodifier
还指定 Visual Basic 如何在其外部文件中查找外部过程。Ansi
和Unicode
两个直接 Visual Basic 在搜索过程中查找它而不修改其名称。Auto
指示 Visual Basic 确定运行时平台的基本字符集,并可能修改外部过程名称,如下所示:在 Unicode 平台(如 Windows)上,首先查找外部过程,无需修改名称。 如果失败,请将“W”追加到外部过程名称的末尾,然后再次查找。
在 ANSI 平台上,首先查找没有名称修改的外部过程。 如果失败,请将“A”追加到外部过程名称的末尾,然后再次查找。
机制。 Visual Basic 使用 .NET Framework 平台调用 (PInvoke) 机制来解析和访问外部过程。 语句
Declare
和 DllImportAttribute 类都自动使用此机制,你不需要任何 PInvoke 知识。 有关详细信息,请参阅 演练:调用 Windows API。
重要
如果外部过程在公共语言运行时(CLR)外部运行,则它是 非托管代码。 调用此类过程(例如 Windows API 函数或 COM 方法)时,可能会向应用程序公开安全风险。 有关详细信息,请参阅 非托管代码的安全编码准则。
示例 1
以下示例声明对 Function
返回当前用户名的过程的外部引用。 然后,它调用外部过程 GetUserNameA
作为过程的一部分 getUser
。
Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (
ByVal lpBuffer As String, ByRef nSize As Integer) As Integer
Sub GetUser()
Dim buffer As String = New String(CChar(" "), 25)
Dim retVal As Integer = GetUserName(buffer, 25)
Dim userName As String = Strings.Left(buffer, InStr(buffer, Chr(0)) - 1)
MsgBox(userName)
End Sub
示例 2
它提供了 DllImportAttribute 在非托管代码中使用函数的替代方法。 以下示例在不使用语句的情况下 Declare
声明导入的函数。
' Add an Imports statement at the top of the class, structure, or
' module that uses the DllImport attribute.
Imports System.Runtime.InteropServices
<DllImportAttribute("kernel32.dll", EntryPoint:="MoveFileW",
SetLastError:=True, CharSet:=CharSet.Unicode,
ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)>
Public Shared Function MoveFile(ByVal src As String,
ByVal dst As String) As Boolean
' This function copies a file from the path src to the path dst.
' Leave this function empty. The DLLImport attribute forces calls
' to MoveFile to be forwarded to MoveFileW in KERNEL32.DLL.
End Function