欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【C#】调用DLL文件

程序员文章站 2022-06-24 22:30:14
...

实际使用C#的过程中,并不一定所有的函数都需要自己写,可以直接使用已经存在的功能,这些功能一般封装在DLL文件中。

C#中的DLL文件又分为托管DLL和非托管DLL。

托管DLL文件是在 .NET 环境下生成的dll文件,在公共语言运行库(Common Language Runtime,简称CLR)中能够直接引用的。比如封装各种命名空间的DLL文件,包括System.dll。

非托管DLL文件不是在 .NET 环境中生成的,是一般的动态链接库,不能在公共语言运行库中直接调用,需要经过 .Net框架提供的“平台调用”服务。以下只讨论非托管DLL文件的调用。

在托管代码中使用"平台调用"服务调用非托管DLL中封装的函数时,“平台服务”将依次执行以下操作:
1. 定位包含该函数所在的DLL文件。
2. 将该DLL文件加载到内存中。
3. 定位函数在内存中的地址并将其参数推到堆栈上,根据需要封送数据。
4. 将控件转移给非托管函数。 这样整个函数调用完成。

MSDN中的平台调用数据类型中列出了非托管C类型和托管类型的替代关系。

使用DLLImport申明Windows API函数

DLLImport定义如下:

namespace System.Runtime.InteropServices
{
    [AttributeUsage(AttributeTargets.Method)]
    public class DllImportAttribute: System.Attribute
    {
        public DllImportAttribute(string dllName){...}   //定位参数为dllName
        public CallingConvention CallingConvention;      //入口点调用约定
        public CharSet CharSet;                          //入口点采用的字符集
        public string EntryPoint;                        //入口点名称或序号
        public bool ExactSpelling;                       //是否必须与指示的入口点拼写完全一致,默认false
        public bool PreserveSig;                         //方法的签名是被保留还是被转换
        public bool SetLastError;                        //FindLastError方法的返回值保存在这里
        public string Value {get {...}}                            
    } 
}  

DllImport会按照顺序自动去寻找的地方:
1. exe所在目录
2. System32目录
3. 环境变量目录

典型例子:

/// [DllImport("xx.dll", EntryPoint="c++中方法名")]
/// public static extern void 转化后的C#方法名(bool b, int i);
/// 比如在C++类库中有个方法:void CFunction(bool b, int i);
/// 你在C#中调用时,先创建一个类
class CSClass
{
  [DllImport("xx.dll", EntryPoint="CFunction")]
  public static extern void CSFunction(bool b, int i);
}
/// 使用的时候就:
CSClass.CSFunction(true, 1);      //方法名可以相同,不一定要改