C# 调用 DLL 教程:使用 DllImport 属性

需积分: 10 20 下载量 20 浏览量 更新于2024-09-21 收藏 18KB DOCX 举报
"C#如何调用dll,详细步骤解析" 在C#编程中,有时我们需要利用已有的非托管代码,例如C++编写的动态链接库(DLL),来扩展功能或利用特定的操作系统服务。C#提供了`DllImport`特性,允许我们直接调用这些DLL中的函数。下面将详细讲解如何使用C#进行DLL调用。 首先,`DllImport`特性位于`System.Runtime.InteropServices`命名空间中。这个特性用于装饰方法,表明该方法是调用外部DLL中的函数。MSDN文档指出,`DllImportAttribute`提供了调用非托管DLL导出函数所需的信息,其中最重要的是指定包含入口点的DLL的名称。 `DllImport`特性的定义如下: ```csharp namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method)] public class DllImportAttribute : Attribute { public DllImportAttribute(string dllName) {} public CallingConvention CallingConvention; public CharSet CharSet; public string EntryPoint; public bool ExactSpelling; public bool PreserveSig; public bool SetLastError; public string Value { get; } } } ``` 使用`DllImport`时需要注意以下几点: 1. `DllImport`只能应用在方法声明上。 2. 必须提供`dllName`参数,它指定了包含要导入方法的DLL的名称。 3. `DllImport`有五个可选参数: - `CallingConvention`:设置函数的调用约定,如`CallingConvention.Cdecl`或`CallingConvention.StdCall`。若不指定,默认为`CallingConvention.Winapi`。 - `CharSet`:指定字符集,例如`CharSet.Ansi`或`CharSet.Unicode`,用于确定字符串参数的编码。默认为`CharSet.Auto`,自动选择适当的字符集。 - `EntryPoint`:指定DLL中函数的实际入口点名称。如果未指定,则默认使用方法的名称。 - `ExactSpelling`:如果为`true`,则表示函数名必须与DLL中的确切名称匹配,不允许自动添加或删除“_”前缀。默认为`false`,允许自动转换。 - `PreserveSig`:如果为`true`,表示当返回类型为`int`或`void`时,即使发生异常,也会保留签名信息。默认为`true`。 - `SetLastError`:如果为`true`,则调用DLL后会设置`System.Win32.Win32ErrorCode.LastError`。默认为`false`。 调用示例: 假设我们有一个名为`MyDll.dll`的DLL,其中有一个函数`AddNumbers(int a, int b)`,我们可以这样在C#中调用它: ```csharp using System; using System.Runtime.InteropServices; public class MyDllWrapper { [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int AddNumbers(int a, int b); } public class Program { public static void Main() { int result = MyDllWrapper.AddNumbers(5, 7); Console.WriteLine("The result is: " + result); } } ``` 在这个例子中,`AddNumbers`方法使用了`DllImport`特性,并指定了DLL名称和调用约定。在`Main`方法中,我们直接调用这个静态方法,就像调用任何其他C#方法一样。 总结,C#通过`DllImport`特性实现了对非托管DLL的调用,这为我们提供了与现有非托管代码交互的能力,从而极大地拓展了C#的功能范围。在实际应用中,务必注意参数类型、调用约定以及字符集的正确配置,以确保调用成功并避免潜在的问题。