Declare 语句
更新:2007 年 11 月
声明对在外部文件中实现的过程的引用。
[ <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 中的访问级别。
Shadows
可选项。请参见 Shadows。charsetmodifier
可选项。指定字符集和文件搜索信息。可以是如下内容之一:Sub
可选项,但是 Sub 或 Function 必须出现。指明外部过程并不返回值。Function
可选项,但是 Sub 或 Function 必须出现。指明外部过程返回值。name
必选。此外部引用的名称。有关更多信息,请参见已声明元素的名称。Lib
必选。引入 Lib 子句,该子句指定包含所声明过程的文件。libname
必选。包含所声明过程的文件的名称。Alias
可选项。指明无法在所声明过程的文件内依据 name 中指定的名称标识该过程。您在 aliasname 中指定其标识。aliasname
如果使用 Alias 关键字,则为必选项。按以下两种方式之一标识过程的字符串:过程在其文件内的入口点名称,括在引号 ("") 内
- 或 -
在数字符号 (#)后跟一个整数,指定过程入口点在其文件内的序号
parameterlist
如果过程接受参数,则为必选项。请参见参数列表。returntype
如果指定了 Function,并且 Option Strict 为 On,则为必选项。过程所返回值的数据类型。
备注
有时,您需要调用在项目外部的某个文件(如 DLL 或代码资源)中定义的过程。当您这样做时,Visual Basic 编译器没有权限访问其正确调用过程所需的信息,例如过程的位置、标识方式、调用顺序和返回类型,以及过程使用的字符串字符集。Declare 语句创建一个对外部过程的引用,并提供这些必需的信息。
仅可以在模块级别使用 Declare。这意味着,外部引用的声明上下文必须是类、结构或模块,不能是源文件、命名空间、接口、过程或块。有关更多信息,请参见声明上下文和默认访问级别。
外部引用默认为 Public (Visual Basic) 访问。可以使用访问修饰符来调整它们的访问级别。
规则
**属性。**可以将属性应用于外部引用。所应用的任何属性都只在项目中有效,在外部文件中无效。
**修饰符。**外部过程是隐式共享的 ( Shared (Visual Basic)) 的。声明外部引用时不能使用 Shared 关键字,也不能改变它的共享状态。
外部过程不能参与重写过程、实现接口成员或处理事件。因此,不能在 Declare 语句中使用 Overrides、Overridable、NotOverridable、MustOverride、Implements 或 Handles 关键字。
**外部过程名称。**不必(在 name 中)为此外部引用指定与过程在其外部文件内的入口点名称 (aliasname) 相同的名称。可以使用 Alias 子句来指定入口点名称。如果外部过程具有与 Visual Basic 保留修饰符或变量、过程或同一范围中的任何其他编程元素相同的名称,这一点可能十分有用。
说明: 大多数 DLL 中的入口点名称都区分大小写。
**外部过程编号。**或者,您可以使用 Alias 子句来指定外部文件的导出表内入口点的序号。为此,您可使用数字符号 (#) 作为 aliasname 的开头。如果不允许在 Visual Basic 中使用外部过程名称中的任何字符,或者,如果外部文件在导出过程时未使用名称,则这一点十分有用。
数据类型规则
**参数数据类型。**如果 Option Strict 为 On,您必须指定 parameterlist 中每个参数的数据类型。这可以是任何数据类型或枚举、结构、类或接口的名称。在 parameterlist 内,您使用 As 子句来指定要传递给每个参数的变量的数据类型。
说明: 如果外部过程不是针对 .NET Framework 编写的,您必须注意应使数据类型相符。例如,如果用 Integer 参数(在 Visual Basic 6.0 中为 16 位)声明对 Visual Basic 6.0 过程的引用,则必须在 Declare 语句中将对应的变量标识为 Short,因为在 Visual Basic 中它是 16 位的整数类型。同样,Long 在 Visual Basic 6.0 中具有不同的数据宽度,并且 Date 的实现方式也不同。
**返回数据类型。**如果外部过程是 Function,并且 Option Strict 设置为 On,您必须指定返回到调用代码的值的数据类型。这可以是任何数据类型或枚举、结构、类或接口的名称。
说明: Visual Basic 编译器不会验证您的数据类型是否与外部过程的数据类型兼容。如果存在不匹配现象,公共语言运行库将在运行时产生 MarshalDirectiveException 异常。
默认数据类型。 如果 Option Strict 设置为 Off,并且未在 parameterlist 中指定某个参数的数据类型,Visual Basic 编译器会将对应的变量转换为 Object 数据类型。同样,如果未指定 returntype,编译器会将返回数据类型转换为 Object。
说明: 由于所处理的外部过程有可能是在不同平台上编写的,因此,对数据类型做出任何假定或允许它们采用默认设置会十分危险。指定每个参数和返回值(如果有)的数据类型将会安全很多。这还提高了代码的可读性。
行为
**范围。**外部引用的应用范围覆盖了其整个类、结构或模块。
**生存期。**外部引用具有与声明它的类、结构或模块相同的生存期。
**调用外部过程。**调用外部过程的方式与调用 Function 或 Sub 过程相同——都是通过在表达式中使用它(如果返回值),或通过在 Call 语句 (Visual Basic) 中指定它(如果不返回值)。
您将完全按照 Declare 语句中的 parameterlist 指定的方式将变量传递给外部过程。不要考虑参数最初在外部文件中的声明方式。同样,如果存在返回值,请完全按照 Declare 语句中 returntype 指定的方式使用它。
**字符集。**可以在 charsetmodifier 中指定 Visual Basic 在调用外部过程时应如何封送字符串。Ansi 修饰符指示 Visual Basic 将所有字符串封送为 ANSI 值,Unicode 修饰符则指示它将所有字符串封送为 Unicode 值。Auto 修饰符指示 Visual Basic 依据 .NET Framework 规则,基于外部引用 name 或 aliasname(如果已指定)封送字符串。默认值为 Ansi。
charsetmodifier 还指定 Visual Basic 应如何在其外部文件内查找外部过程。Ansi 和 Unicode 都指示 Visual Basic 在搜索过程中查找外部过程而不修改其名称。Auto 指示 Visual Basic 确定运行时平台的基本字符集,并在可能时修改外部过程名称,如下所示:
在 ANSI 平台(如 Windows 95、Windows 98 或 Windows Millennium Edition)上,将首先查找外部过程,而不修改名称。如果查找失败,则在外部过程名称结尾附加“A”,并再次查找。
在 Unicode 平台(如 Windows NT、Windows 2000 或 Windows XP)上,将首先查找外部过程,而不修改名称。如果查找失败,则在外部过程名称结尾附加“W”,并再次查找。
**机制。**Visual Basic 使用 .NET Framework 的平台调用 (PInvoke) 机制来解析和访问外部过程。Declare 语句和 DllImportAttribute 类都会自动使用此机制,您无需对 PInvoke 有任何了解。有关更多信息,请参见演练:调用 Windows API。
安全说明: |
---|
如果外部过程在公共语言运行库 (CLR) 外部运行,则它为非托管代码。当您调用此类过程(例如,Win32 API 函数或 COM 方法)时,可能会使应用程序面临安全风险。有关更多信息,请参见非托管代码。 |
示例
下面的示例声明对 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
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
请参见
任务
概念
数据类型更改(针对 Visual Basic 6.0 用户)
Integer 数据类型(针对 Visual Basic 6.0 用户)