c# DLLImport 属性 讲解
### C# 中的 DLLImport 属性详解 在 C# 编程中,当我们需要调用非托管代码(通常是 Windows API 函数)时,就需要用到 `DllImport` 属性。这一特性使得 C# 开发者能够方便地访问由 C/C++ 编写并封装在 DLL 文件中的函数。 #### 什么是 DLLImport? `DllImport` 是一个属性,它用于指定一个非托管 DLL 的名称,该 DLL 包含被调用的方法实现。通过这个属性,我们可以在 C# 代码中声明一个方法,并告诉 CLR (Common Language Runtime) 这个方法的实际实现位于哪个 DLL 文件中。这对于与 Windows API 或其他非托管代码交互非常有用。 #### 基本使用 在使用 `DllImport` 之前,我们需要了解几个关键概念: - **DllImportAttribute**:这是用来标记一个静态方法的属性,该静态方法将被编译器识别为外部方法。 - **DLL 名称**:`DllImport` 需要指定 DLL 的名称,这通常是 Windows API 的 DLL 名称,如 `kernel32.dll`。 - **入口点**:`EntryPoint` 属性用于指定在 DLL 中实际调用的函数名。 - **字符集**:`CharSet` 属性指定了调用 DLL 时使用的字符集。 - **错误设置**:`SetLastError` 属性表示是否应该设置最后一个错误代码。 - **调用约定**:`CallingConvention` 指定了调用方法的约定。 #### 示例解析 下面通过具体的示例来进一步理解这些概念: ```csharp [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); ``` 在这个例子中: - **DLL 名称**:`user32.dll`,这是一个常用的 Windows API DLL。 - **字符集**:`CharSet.Auto` 表示自动选择合适的字符集。在大多数情况下,这意味着使用 `CharSet.Unicode`,因为现代 Windows 版本默认支持 Unicode。 - **错误设置**:`SetLastError = true` 表示每次调用此方法后都会设置一个错误代码,这可以通过 `Marshal.GetLastWin32Error()` 来获取。 - **入口点**:这里没有明确指定 `EntryPoint`,意味着方法名称与 DLL 中的函数名称相同。 #### 入口点(EntryPoint) `EntryPoint` 属性用来指定 DLL 中的实际函数名称。有时候,C# 方法名和 DLL 中的函数名可能不完全一致,这时就需要使用 `EntryPoint` 来指定确切的函数名。例如: ```csharp [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern bool MessageBeep(int uType); // 如果 DLL 中的函数名为 "MessageBeepA",则需要这样指定: [DllImport("kernel32.dll", EntryPoint = "MessageBeepA", CharSet = CharSet.Auto, SetLastError = true)] static extern bool MessageBeepAlt(int uType); ``` #### 字符集(CharSet) `CharSet` 属性非常重要,因为它决定了如何处理字符串参数。通常有以下几种选项: - `CharSet.Ansi`:使用 ANSI 字符集。 - `CharSet.Unicode`:使用 Unicode 字符集。 - `CharSet.Auto`:自动选择。在现代系统上,默认为 `CharSet.Unicode`。 选择正确的字符集对于确保正确传递字符串参数至关重要。 #### 设置最后的错误(SetLastError) 当设置了 `SetLastError` 为 `true` 时,每次调用 DLL 函数之后都会记录一个错误代码。这通常用于调试目的,可以帮助确定调用失败的原因。 ```csharp [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern bool ReadDirectoryChangesW(IntPtr hDirectory, byte[] lpBuffer, int nBufferLength, bool bWatchSubtree, uint dwNotifyFilter, out int lpBytesReturned, IntPtr overlapped, IntPtr hEvent); ``` 如果调用 `ReadDirectoryChangesW` 失败,可以使用 `Marshal.GetLastWin32Error()` 获取错误代码。 #### 调用约定(CallingConvention) `CallingConvention` 属性定义了如何传递参数以及返回值。常见的调用约定有: - `CallingConvention.StdCall`:标准调用约定。 - `CallingConvention.Cdecl`:C 语言调用约定。 - `CallingConvention.Winapi`:Windows API 调用约定,这是默认值。 例如,对于 `kernel32.dll` 中的函数,通常会使用 `CallingConvention.StdCall`。 ### 总结 `DllImport` 是 C# 中非常重要的特性,它允许开发者轻松地调用非托管代码。通过正确配置 `DllImport` 属性,可以确保与 Windows API 的交互既高效又准确。理解和掌握这些属性的使用方法对于任何希望进行底层编程或与操作系统紧密集成的 C# 开发者来说都是非常重要的。



















- 粉丝: 4
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源


