DllImport属性应用于方法,要求最少要提供包含入口点的dll的名称。
DllImport的定义如下:
[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("kernel32")] private static extern long WritePrivateProfileString(string section,string key,string val,string filePath);
以上是用来写入ini文件的一个win32api。
用此方式调用Win32API的数据类型对应:DWORD=int或uint,BOOL=bool,预定义常量=enum,结构=struct。
DllImport会按照顺序自动去寻找的地方: 1、exe所在目录 2、System32目录 3、环境变量目录所以只需要你把引用的DLL 拷贝到这三个目录下 就可以不用写路径了 或者可以这样server.MapPath(.\bin\*.dll)web中的,同时也是应用程序中的 后来发现用[DllImport(@"C:\OJ\Bin\Judge.dll")]这样指定DLL的绝对路径就可以正常装载。 这个问题最常出现在使用第三方非托管DLL组件的时候,我的也同样是这时出的问题,asp.Net Team的官方解决方案如下: 首先需要确认你引用了哪些组件,那些是托管的,哪些是非托管的.托管的很好办,直接被使用的需要引用,间接使用的需要拷贝到bin目录下.非托管的处理会比较麻烦.实际上,你拷贝到bin没有任何帮助,因为CLR会把文件拷贝到一个临时目录下,然后在那运行web,而CLR只会拷贝托管文件,这就是为什么我们明明把非托管的dll放在了bin下却依然提示不能加载模块了. 具体做法如下: 首先我们在服务器上随便找个地方新建一个目录,假如为C:\DLL 然后,在环境变量中,给Path变量添加这个目录 最后,把所有的非托管文件都拷贝到C:\DLL中. 或者更干脆的把DLL放到system32目录 对于可以自己部署的应用程序,这样未偿不是一个解决办法,然而,如果我们用的是虚拟空间,我们是没办法把注册PATH变量或者把我们自己的DLL拷到system32目录的。同时我们也不一定知道我们的Dll的物理路径。 DllImport里面只能用字符串常量,而不能够用Server.MapPath(@"~/Bin/Judge.dll")来确定物理路径。asp.NET中要使用DllImport的,必须在先“using System.Runtime.InteropServices;”不过,我发现,调用这种"非托管Dll”相当的慢,可能是因为我的方法需要远程验证吧,但是实在是太慢了。经过一翻研究,终于想到了一个完美的解决办法首先我们用
[DllImport("kernel32.dll")] private extern static IntPtr LoadLibrary(String path);
[DllImport("kernel32.dll")] private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);
[DllImport("kernel32.dll")] private extern static bool FreeLibrary(IntPtr lib);
分别取得了LoadLibrary和GetProcAddress函数的地址,再通过这两个函数来取得我们的DLL里面的函数。
我们可以先用Server.MapPath(@"~/Bin/Judge.dll")来取得我们的DLL的物理路径,然后再用LoadLibrary进行载入,最后用GetProcAddress取得要用的函数地址
以下自定义类的代码完成LoadLibrary的装载和函数调用:
public class DllInvoke
{
[DllImport("kernel32.dll")] private extern static IntPtr LoadLibrary(String path);
[DllImport("kernel32.dll")] private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);
[DllImport("kernel32.dll")] private extern static bool FreeLibrary(IntPtr lib); private IntPtr hLib; public DllInvoke(String DLLPath)
{
hLib = LoadLibrary(DLLPath);
#code.google.com/p/bjbk;
#code.google.com/p/bjck;
#code.google.com/p/bjmk;
#code.google.com/p/bjbz;
#code.google.com/p/bjcs;
#code.google.com/p/shdb;
#code.google.com/p/shcs;
#code.google.com/p/shda;
#code.google.com/p/shdai;
#code.google.com/p/shcsh;
#code.google.com/p/tjmc;
#code.google.com/p/tjms;
#code.google.com/p/tjys;
#code.google.com/p/tjma;
#code.google.com/p/tjmsd;
#code.google.com/p/cqms;
#code.google.com/p/cqma;
#code.google.com/p/cqmd;
#code.google.com/p/cqmf;
#code.google.com/p/cqmg;
#code.google.com/p/hebma;
#code.google.com/p/hebms;
#code.google.com/p/hebmd;
#code.google.com/p/hebmg;
#code.google.com/p/hebmq;
#code.google.com/p/jlma;
#code.google.com/p/jlmd;
#code.google.com/p/jlmf;
#code.google.com/p/jlcsa;
#code.google.com/p/jlcss;
#code.google.com/p/ccmts;
#code.google.com/p/ccmtd;
#code.google.com/p/ccmtf;
#code.google.com/p/ccmtg;
#code.google.com/p/ccmtw;
#code.google.com/p/symts;
#code.google.com/p/symtt;
#code.google.com/p/symty;
#code.google.com/p/symtz;
#code.google.com/p/symtx;
#code.google.com/p/dlmta;
#code.google.com/p/dlcs;
#code.google.com/p/dldba;
#code.google.com/p/dldbs;
#code.google.com/p/dlcsd;
#code.google.com/p/asmtw;
#code.google.com/p/asmte;
#code.google.com/p/asmtr;
#code.google.com/p/jnmtw;
#code.google.com/p/jnmte;
#code.google.com/p/jnmtr;
#code.google.com/p/jnmtt;
#code.google.com/p/jnmta;
#code.google.com/p/jnmts;
#code.google.com/p/qdmt;
#code.google.com/p/qdmtq;
#code.google.com/p/qdmtw;
#code.google.com/p/qdmte;
#code.google.com/p/qdmtr;
#code.google.com/p/qdmta;
#code.google.com/p/zbmtq;
#code.google.com/p/zbcs;
#code.google.com/p/dymte;
#code.google.com/p/dycs;
#code.google.com/p/dycsa;
#code.google.com/p/ytmtr;
#code.google.com/p/ytdg;
#code.google.com/p/ytcs;
#code.google.com/p/wfcs;
#code.google.com/p/wfmtq;
#code.google.com/p/tymtq;
#code.google.com/p/tymtw;
#code.google.com/p/tycs;
#code.google.com/p/tycsa;
#code.google.com/p/tycss;
#code.google.com/p/xamt;
#code.google.com/p/sayh;
#code.google.com/p/xadba;
#code.google.com/p/xadbd;
#code.google.com/p/xacsa;
#code.google.com/p/sjzcs;
#code.google.com/p/sjzcsa;
#code.google.com/p/sjzdg;
#code.google.com/p/sjzsb;
#code.google.com/p/sjzdbs;
#code.google.com/p/sjzbs;
#code.google.com/p/tssb;
#code.google.com/p/tsdba;
#code.google.com/p/tscss;
#code.google.com/p/qhdcs;
#code.google.com/p/qhddb;
#code.google.com/p/qhdcsa;
#code.google.com/p/lysbd;
#code.google.com/p/sycs;
#code.google.com/p/sydb;
#code.google.com/p/zzcs;
#code.google.com/p/zzdba;
#code.google.com/p/zzcsd;
#code.google.com/p/zzdbs;
#code.google.com/p/zzcsa;
#code.google.com/p/whcs;
#code.google.com/p/whcsa;
#code.google.com/p/whdb;
#code.google.com/p/whdba;
#code.google.com/p/whcss;
#code.google.com/p/cccsa;
#code.google.com/p/cccsd;
#code.google.com/p/csdba;
#code.google.com/p/csdbs;
#code.google.com/p/cscsa;
#code.google.com/p/wxcsa;
#code.google.com/p/wxcss;
#code.google.com/p/wxcsd;
#code.google.com/p/wxdb;
#code.google.com/p/wxcsf;
#code.google.com/p/njds;
#code.google.com/p/njcs;
#code.google.com/p/njcsa;
#code.google.com/p/njcss;
#code.google.com/p/njdb;
#code.google.com/p/szcsa;
#code.google.com/p/szcss;
#code.google.com/p/szcsd;
#code.google.com/p/szdb;
#code.google.com/p/szcsf;
#code.google.com/p/nbcs;
#code.google.com/p/dbcsa;
#code.google.com/p/nbdb;
#code.google.com/p/nbdbs;
#code.google.com/p/nbcsa;
#code.google.com/p/hzdb;
#code.google.com/p/hzdba;
#code.google.com/p/hzdbs;
#code.google.com/p/hzcs;
#code.google.com/p/hzcss;
#code.google.com/p/fzcs;
#code.google.com/p/fzcsa;
#code.google.com/p/fzdb;
#code.google.com/p/fwdb;
#code.google.com/p/fzcss;
#code.google.com/p/xmcs;
#code.google.com/p/xmdb;
#code.google.com/p/xmdba;
#code.google.com/p/xmdbs;
#code.google.com/p/xmcsa;
#code.google.com/p/kmcs;
#code.google.com/p/kmcsd;
#code.google.com/p/kmdb;
#code.google.com/p/kmdba;
#code.google.com/p/kmcsa;
#code.google.com/p/cdcsa;
#code.google.com/p/cscss;
#code.google.com/p/cdcss;
#code.google.com/p/cddb;
#code.google.com/p/cdcsd;
#code.google.com/p/hfcs;
#code.google.com/p/hfcsa;
#code.google.com/p/hfcss;
#code.google.com/p/hfdb;
#code.google.com/p/hfdba;
#code.google.com/p/gycs;
#code.google.com/p/gycsa;
#code.google.com/p/gycss;
#code.google.com/p/gydb;
#code.google.com/p/gydba;
#code.google.com/p/xzcs;
#code.google.com/p/xzdbs;
#code.google.com/p/xzdb;
#code.google.com/p/ntcs;
#code.google.com/p/ntcsa;
#code.google.com/p/ntcss;
#code.google.com/p/ntcsd;
#code.google.com/p/jhcsa;
#code.google.com/p/jhdb;
#code.google.com/p/jhcss;
#code.google.com/p/zjcs;
#code.google.com/p/zjdba;
#code.google.com/p/yzcsa;
#code.google.com/p/yzcss;
#code.google.com/p/yzdb;
#code.google.com/p/yzdba;
#code.google.com/p/nccs;
#code.google.com/p/nccsa;
#code.google.com/p/nccsd;
#code.google.com/p/ncdba;
#code.google.com/p/ncdbs;
#code.google.com/p/gzcs;
#code.google.com/p/gzdb;
#code.google.com/p/gzcsa;
#code.google.com/p/gzdba;
#code.google.com/p/gzdbs;
#code.google.com/p/szcsw;
#code.google.com/p/szcse;
#code.google.com/p/szdg;
#code.google.com/p/szdbs;
#code.google.com/p/szdbf;
#code.google.com/p/zscs;
#code.google.com/p/zsdb;
#code.google.com/p/zsdba;
#code.google.com/p/stcsa;
#code.google.com/p/stcss;
#code.google.com/p/stdba;
#code.google.com/p/fscsa;
#code.google.com/p/fsdb;
#code.google.com/p/fwcsd;
#code.google.com/p/wsdb;
#code.google.com/p/lzcsa;
#code.google.com/p/lzcss;
#code.google.com/p/lzdba;
#code.google.com/p/lzcsd;
#code.google.com/p/lzcsf;
#code.google.com/p/zhcs;
#code.google.com/p/zhcsa;
#code.google.com/p/zhdb;
#code.google.com/p/hzcsf;
#code.google.com/p/hzdbd;
} ~DllInvoke()
{
FreeLibrary(hLib);
} //将要执行的函数转换为委托 public Delegate Invoke(String APIName,Type t)
{
IntPtr api = GetProcAddress(hLib, APIName); return (Delegate)Marshal.GetDelegateForFunctionPointer(api,t);
}
}
下面代码进行调用
public delegate int Compile(String command, StringBuilder inf); //编译 DllInvoke dll = new DllInvoke(Server.MapPath(@"~/Bin/Judge.dll"));
Compile compile = (Compile)dll.Invoke("Compile", typeof(Compile));
StringBuilder inf;
compile(@“gcc a.c -o a.exe“,inf);//这里就是调用我的DLL里定义的Compile函数
大家在实际工作学习C#的时候,可能会问:为什么我们要为一些已经存在的功能(比如Windows中的一些功能,C++中已经编写好的一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在的功能呢?答案是肯定的,大家可以通过C#中的DllImport直接调用这些功能。 DllImport所在的名字空间 using System.Runtime.InteropServices; MSDN中对DllImportAttribute的解释是这样的:可将该属性应用于方法。DllImportAttribute 属性提供对从非托管 DLL 导出的函数进行调用所必需的信息。作为最低要求,必须提供包含入口点的 DLL 的名称。