浅浅的说说DllImport属性

来源:互联网 发布:数据字典怎么写 编辑:程序博客网 时间:2024/04/29 19:11

    DllImport属性的功能:

    [MSDN]从托管应用程序调用非托管代码。(托管代码指的是必须依靠.NET框架解释运行的代码,非托管代码一般指的是传统的不需要借助.NET框架解释的代码。在.NET出现之前,如VB,C++,DELPHI编写的程序都是非托管代码。)

     

    在开发时会经常遇到的,比如商务拨号系统中,直接和话媒硬件打交道的代码集成在一个用C编写的dll中,而在.net下引用这个dll中的方法时,就需要用到DllImport。

     

    比如

    [DllImport("phonic_ubox.dll")]public static extern void ubox_close();  // extern修饰符用于声明在外部实现的方法

     

    DLL对应的API文档

    void WINAPI    ubox_close(void)

    功  能:关闭设备

    说  明:  最后程序退出,必须调用这个函数,否则会出现异常

     

    示例

    使用 C 程序创建一个 DLL,使用 C# 程序调用该 DLL。

     

        int __declspec(dllexport) SampleMethod(int i)      {        return i*10;      }  

    从 C# 程序内调用。

        using System;      using System.Runtime.InteropServices;      public class MainClass       {        [DllImport("Cmdll.dll")]        public static extern int SampleMethod(int x);              static void Main()         {            Console.WriteLine("SampleMethod() returns {0}.", SampleMethod(5));        }      }  

     

    输出

    SampleMethod() returns 50.

     

    DllImport会按照顺序自动去寻找引用的dll:

     1、项目下的bin目录下 2、System32目录 3、环境变量目录。即只需把ddl放入任一目录下即可。

     

    引入问题:非托管dll放在bin下无济于事。

    Asp.Net Team的官方解决方案如下:托管的很好办,直接被使用的需要引用,间接使用的需要拷贝到bin目录下。非托管的处理会比较麻烦.实际上,你拷贝到bin没有任何帮助,因为CLR会把文件拷贝到一个临时目录下,然后在那运行web,而CLR 只会拷贝托管文件,这就是为什么我们明明把非托管的dll放在了bin下却依然提示不能加载模块了. 

     

    对于自己部署的应用程序,引用非托管dll完全采用后两种方式。

     

    然而,如果我们用的是虚拟空间,我们是没办法把注 册PATH变量或者把我们自己的DLL拷到system32目录的。

     

    网上找到的解决方法,因为尚未涉及到,所以只是简单的罗列下:

    DllImport里面只能用字符 串常量,而不能够用Server.MapPath(@"~/Bin/Judge.dll")来确定物理路径。经过一翻研究,终于想到了一个完美的解决办法首先我们用

     

    [DllImport("kernel32.dll")]

    privateexternstatic IntPtr LoadLibrary(String path);

     

    [DllImport("kernel32.dll")]

    privateexternstatic IntPtr GetProcAddress(IntPtr lib, String funcName);

     

    [DllImport("kernel32.dll")]

    privateexternstaticbool FreeLibrary(IntPtr lib);

    分别取得了LoadLibrary和GetProcAddress函数的地址,再通过这两个函数来取得我们的DLL里面的函数。

    我们可以先用Server.MapPath(@"~/Bin/Judge.dll")来取得我们的DLL的物理路径,然后再用LoadLibrary进行载入,最后用GetProcAddress取得要用的函数地址

     

    以下自定义类的代码完成LoadLibrary的装载和函数调用:

     

    publicclass DllInvoke

    {           

    [DllImport("kernel32.dll")]

    privateexternstatic IntPtr LoadLibrary(String path);

     

    [DllImport("kernel32.dll")]  

    privateexternstatic IntPtr GetProcAddress(IntPtr lib, String funcName);

     

    [DllImport("kernel32.dll")]    

    privateexternstaticbool FreeLibrary(IntPtr lib);    

     

    private IntPtr hLib;  

     

    public DllInvoke(String DLLPath)  

    {          

    hLib = LoadLibrary(DLLPath); 

    }      

     

    ~DllInvoke()    

    {       

    FreeLibrary(hLib); 

    }       

     

    //将要执行的函数转换为委托 

    public Delegate Invoke(String APIName,Type t)    

    {          

    IntPtr api = GetProcAddress(hLib, APIName);  

    return (Delegate)Marshal.GetDelegateForFunctionPointer(api,t);    

    }

    }

    下面代码进行调用

     

    publicdelegateint 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函数



    小结

    我说DllImport的伟大之处在于,.net平台没有闭关锁国,能够容纳别人,集百家之长。做人也该如此。


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小车临时牌过期了怎么办 驾驶证地址错了一个字怎么办 驾驶证名下车辆有违章怎么办 a2如果扣12分怎么办 b2一次超速12分怎么办 b2本扣了12分怎么办 驾照扣了27分怎么办 大车一次扣12分怎么办 a2驾照扣10分怎么办 驾驶证强制降级没给驾驶证怎么办 6P升11.2卡了怎么办 b2驾照记满12分怎么办 c1驾驶证没分了怎么办 驾照扣了15分怎么办 驾驶证暂扣六个月后怎么办 醉驾交警不通知怎么办 参军后地方驾驶证年审怎么办 军人驾驶证到期身份证注销了怎么办 资格证脱审30天怎么办 驾驶证c证扣6分怎么办 驾照被扣了9分怎么办 驾驶证被扣了9分怎么办 a2驾驶本扣3分怎么办 c1e没过扣了满分怎么办 c1一下扣12分怎么办 换证体检过不了怎么办 唐山驾驶本到期换本怎么办 北京居住证变更地址了怎么办 眼睛弱视驾驶证换证不了怎么办? 驾照的分扣完了怎么办 驾照被扣了3分怎么办 交警扣了行驶证怎么办 报考驾照时手机号录错怎么办 摩托车被交警队拖走怎么办 汽车牌照被偷了怎么办 代理品牌个体工商营业证怎么办 2地交社保怎么办退休 驾驶证脱审3月怎么办 a1一次性扣12分怎么办 驾照在外地掉了怎么办 在外市考的驾照怎么办