《dll import 属性》由会员分享,可在线阅读,更多相关《dll import 属性(25页珍藏版)》请在金锄头文库上搜索。
1、请问 C#高手: DllImport(kernel32.dll)是什么意思? 请问 C#高手: DllImport(kernel32.dll)是什么意思?这叫引入 kernel32.dll 这个动态连接库。 这个动态连接库里面包含了很多 WindowsAPI 函数, 如果你想使用这面的函数,就需要这么引入。举个例子: DllImport(kernel32.dll) private static extern void 函数名(参数,参数); 函数名就是一个属于 kernel32.dll 里的一个函数。完了你就可以用那个函数了。 kernel32.dll 调用 kernel32.dll 这个 D
2、LL 里面的 API 接口! 系统 API 例如 DllImport(user32.dll)/-引入 API public static extern ReturnType FunctionName(type arg1,type arg2,.);/-声明方法 调用该方法是和调用普通方法没区别 DLL Import 属性 现在是更深入地进行探讨的时候了。在对托管代码进行 P/Invoke 调用时,DllImportAttribute 类型扮演着重要的角色。DllImportAttribute 的主要作用是给 CLR 指示哪个 DLL 导出您想要调用的函数。相关 DLL 的名称被作为一个构造函数参
3、数传递给 DllImportAttribute。 如果您无法肯定哪个 DLL 定义了您要使用的 Windows API 函数,Platform SDK 文档将为您提供最好的帮助资源。在 Windows API 函数主题文字临近结尾的位置, SDK 文档指定了 C 应用程序要使用该函数必须链接的 .lib 文件。在几乎所有的情况下,该 .lib 文件具有与定义该函数的系统 DLL 文件相同的名称。例如,如果该函数需要 C 应用程序链接到 Kernel32.lib,则该函数就定义在 Kernel32.dll 中。您可以在 MessageBeep 中找到有关 MessageBeep 的 Platfo
4、rm SDK 文档主题。在该主题结尾处,您会注意到它指出库文件是 User32.lib;这表明 MessageBeep 是从 User32.dll 中导出的。 可选的 DllImportAttribute 属性 除了指出宿主 DLL 外,DllImportAttribute 还包含了一些可选属性,其中四个特别有趣:EntryPoint、CharSet、SetLastError 和 CallingConvention。 EntryPoint 在不希望外部托管方法具有与 DLL 导出相同的名称的情况下,可以设置该属性来指示导出的 DLL 函数的入口点名称。当您定义两个调用相同非托管函数的外部方法时
5、,这特别有用。另外,在 Windows 中还可以通过它们的序号值绑定到导出的 DLL 函数。如果您需要这样做,则诸如“#1”或“#129”的 EntryPoint 值指示 DLL 中非托管函数的序号值而不是函数名。 CharSet 对于字符集,并非所有版本的 Windows 都是同样创建的。Windows 9x 系列产品缺少重要的 Unicode 支持,而 Windows NT 和 Windows CE 系列则一开始就使用 Unicode。在这些操作系统上运行的 CLR 将 Unicode 用于 String 和 Char 数据的内部表示。但也不必担心 当调用 Windows 9x API 函
6、数时,CLR 会自动进行必要的转换,将其从 Unicode 转换为 ANSI。 如果 DLL 函数不以任何方式处理文本,则可以忽略 DllImportAttribute 的 CharSet 属性。然而,当 Char 或 String 数据是等式的一部分时,应该将 CharSet 属性设置为 CharSet.Auto。这样可以使 CLR 根据宿主 OS 使用适当的字符集。如果没有显式地设置 CharSet 属性,则其默认值为 CharSet.Ansi。这个默认值是有缺点的,因为对于在 Windows 2000、Windows XP 和 Windows NT 上进行的 interop 调用,它会消
7、极地影响文本参数封送处理的性能。 应该显式地选择 CharSet.Ansi 或 CharSet.Unicode 的 CharSet 值而不是使用 CharSet.Auto 的唯一情况是:您显式地指定了一个导出函数,而该函数特定于这两种 Win32 OS 中的某一种。ReadDirectoryChangesW API 函数就是这样的一个例子,它只存在于基于 Windows NT 的操作系统中,并且只支持 Unicode;在这种情况下,您应该显式地使用 CharSet.Unicode。 有时,Windows API 是否有字符集关系并不明显。一种决不会有错的确认方法是在 Platform SDK
8、中检查该函数的 C 语言头文件。(如果您无法肯定要看哪个头文件,则可以查看 Platform SDK 文档中列出的每个 API 函数的头文件。)如果您发现该 API 函数确实定义为一个映射到以 A 或 W 结尾的函数名的宏,则字符集与您尝试调用的函数有关系。Windows API 函数的一个例子是在 WinUser.h 中声明的 GetMessage API,您也许会惊讶地发现它有 A 和 W 两种版本。 SetLastError 错误处理非常重要,但在编程时经常被遗忘。当您进行 P/Invoke 调用时,也会面临其他的挑战 处理托管代码中 Windows API 错误处理和异常之间的区别。我
9、可以给您一点建议。 如果您正在使用 P/Invoke 调用 Windows API 函数,而对于该函数,您使用 GetLastError 来查找扩展的错误信息,则应该在外部方法的 DllImportAttribute 中将 SetLastError 属性设置为 true。这适用于大多数外部方法。 这会导致 CLR 在每次调用外部方法之后缓存由 API 函数设置的错误。然后,在包装方法中,可以通过调用类库的 System.Runtime.InteropServices.Marshal 类型中定义的 Marshal.GetLastWin32Error 方法来获取缓存的错误值。我的建议是检查这些期望
10、来自 API 函数的错误值,并为这些值引发一个可感知的异常。对于其他所有失败情况(包括根本就没意料到的失败情况),则引发在 System.ComponentModel 命名空间中定义的 Win32Exception,并将 Marshal.GetLastWin32Error 返回的值传递给它。如果您回头看一下图 1 中的代码,您会看到我在 extern MessageBeep 方法的公共包装中就采用了这种方法。 CallingConvention 我将在此介绍的最后也可能是最不重要的一个 DllImportAttribute 属性是 CallingConvention。通过此属性,可以给 CLR
11、 指示应该将哪种函数调用约定用于堆栈中的参数。CallingConvention.Winapi 的默认值是最好的选择,它在大多数情况下都可行。然而,如果该调用不起作用,则可以检查 Platform SDK 中的声明头文件,看看您调用的 API 函数是否是一个不符合调用约定标准的异常 API。 通常,本机函数(例如 Windows API 函数或 C- 运行时 DLL 函数)的调用约定描述了如何将参数推入线程堆栈或从线程堆栈中清除。大多数 Windows API 函数都是首先将函数的最后一个参数推入堆栈,然后由被调用的函数负责清理该堆栈。相反,许多 C-运行时 DLL 函数都被定义为按照方法参数
12、在方法签名中出现的顺序将其推入堆栈,将堆栈清理工作交给调用者。 幸运的是,要让 P/Invoke 调用工作只需要让外围设备理解调用约定即可。通常,从默认值 CallingConvention.Winapi 开始是最好的选择。然后,在 C 运行时 DLL 函数和少数函数中,可能需要将约定更改为 CallingConvention.Cdecl。 C# API 大全 作者:不详 加入时间:4/17/2008 9:41:49 AMC# APIC:ProgramFilesMicrosoftVisual Studio .NET FrameworkSDKSamples Technologies Intero
13、pPlatformInvoke WinAPIsCS 目录下有大量的调用 API的例子。一、调用格式using System.Runtime.InteropServices; /引用此名称空间,简化后面的代码/使用 DllImportAttribute 特性来引入 api 函数,注意声明的是空方法,即方法体为空。DllImport(user32.dll)public static extern ReturnType FunctionName(type arg1,type arg2,.);/调用时与调用其他方法并无区别可以使用字段进一步说明特性,用逗号隔开,如: DllImport( kernel
14、32, EntryPoint=GetVersionEx ) DllImportAttribute 特性的公共字段如下:1、CallingConvention 指示向非托管实现传递方法参数时所用的 CallingConvention 值。CallingConvention.Cdecl : 调用方清理堆栈。它使您能够调用具有 varargs 的函数。CallingConvention.StdCall : 被调用方清理堆栈。它是从托管代码调用非托管函数的默认约定。2、CharSet 控制调用函数的名称版本及指示如何向方法封送 String 参数。此字段被设置为 CharSet 值之一。如果 Char
15、Set 字段设置为 Unicode,则所有字符串参数在传递到非托管实现之前都转换成 Unicode 字符。这还导致向 DLL EntryPoint 的名称中追加字母 “W”。如果此字段设置为 Ansi,则字符串将转换成 ANSI 字符串,同时向 DLL EntryPoint 的名称中追加字母 “A”。大多数 Win32 API 使用这种追加“W” 或“A” 的约定。如果 CharSet 设置为 Auto,则这种转换就是与平台有关的(在 Windows NT 上为 Unicode,在 Windows 98 上为 Ansi)。CharSet 的默认值为 Ansi。CharSet 字段也用于确定将从
16、指定的 DLL 导入哪个版本的函数。CharSet.Ansi 和 CharSet.Unicode 的名称匹配规则大不相同。对于 Ansi 来说,如果将 EntryPoint 设置为“MyMethod”且它存在的话,则返回“MyMethod”。如果 DLL 中没有“MyMethod”,但存在“MyMethodA”,则返回“MyMethodA”。对于 Unicode 来说则正好相反。如果将 EntryPoint 设置为“MyMethod”且它存在的话,则返回“MyMethodW”。如果 DLL 中不存在“MyMethodW”,但存在“MyMethod”,则返回“MyMethod” 。如果使用的是 Auto,则匹配规则与平台有关(在 Windows NT 上为 Unicode,在 Windows 98 上为 Ansi)。如果 ExactSpelling 设置为 true,则只有当 DLL 中存在“MyMethod