zoukankan      html  css  js  c++  java
  • C#调用C++ DLL的方式

         动态链接库(DLL)是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。可以说在windows操作系统中随处可见,打开主分区盘下的system32。在一些项目中,如果有大量运算或者涉及大量算法时通常使用C或C++语言封装成一个dll,开放一些接口供其他程序调用。

      下面是写的一个简单的dll代码,主要做示例,功能非常简单

    1、dll提供外部调用的方法

    extern "C" _declspec(dllexport) int Max(int a,int b);
    extern "C" _declspec(dllexport) int Sum(int a,int b);
    extern "C" _declspec(dllexport) int Min(int a,int b);

    2、方法的实现

    int Max(int a,int b)
    {
        if(a>b)
            return a;
        else
            return b;
    }
    
    int Sum(int a,int b)
    {
        return a+b;
    }
    
    int Min(int a,int b)
    {
        if(a>b)
            return b;
        else
            return a;
    }

    本文主要是介绍使用C#如何调用DLL不是重点,只做简单的介绍

    一、C#调用DLL

    在使用C#调用C++,需要使用系统Kernel32.dll来导入dill,一般需要如下三个函数

            [DllImport("Kernel32",SetLastError=true)]
            private static extern int GetProcAddress(int handle,string funcName);
    
            [DllImport("Kernel32",SetLastError=true)]
            private static extern int LoadLibrary(string dllPath);
    
            [DllImport("Kernel32",SetLastError=true)]
            private static extern int FreeLibrary(int handle);

    其中:

    LoadLibrary方法用来导入Dll

    FreeLibrary方法用来释放Dll

    GetProcAdress方法用来获取Dll中的方法访问的地址。

    然后需要在C#中建立一个和C++中方法对应的方法,以便在C#中调用,我们定义三个委托来完成这件事:

            public delegate int Max(int a, int b);
    
            public delegate int Min(int a, int b);
    
            public delegate int Sum(int a, int b);

    然后我们定义三个委托的实例,使用上面的GetProAdress方法把地址指向委托实例的地址。全部代码如下:

            private int dllHandle = 0;
    
            public Max ProMax
            {
                get;
                set;
            }
    
            public Min ProMin
            {
                set;
                get;
            }
    
            public Sum ProSum
            {
                get;
                set;
            }
    
            // 获取dll中的接口地址
            private static Delegate GetAddress(int dllModule, string functionname, Type t)
            {
                int addr = GetProcAddress(dllModule, functionname);
    
                if (addr == 0)
                    return null;
                else
                    return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t);
            }
    
            public void FreeLinbary()
            {
                if (this.dllHandle >= 32)
                {
                    FreeLibrary(this.dllHandle);
                }
            }
    
            /// <summary>
            /// 加载Dll
            /// </summary>
                /// <returns>是否加载Dll成功</returns> 
            public int LoadDll(string dllPath)
            {
                this.dllHandle = LoadLibrary(dllPath);
    
                if (this.dllHandle >= 32)
                {
                    this.ProMax = (Max)GetAddress(dllHandle, "Max", typeof(Max));
                    this.ProMin = (Min)GetAddress(dllHandle, "Min", typeof(Min));
                    this.ProSum = (Sum)GetAddress(dllHandle, "Sum", typeof(Sum));
                    return 0;
                }
                else
                {
                    return 1;
                }
            }
    整个调用流程比较简单,在C#调用C++写的Dll过程中,关键是参数类型的对应方面容易出错,C++中的数据类型和C#中还是有些区别的,比如char在C#中是两个字节,在C++是一个字节。在C++中使用了指针,在C#中同样需要使用IntPtr获取其指针地址。 
  • 相关阅读:
    【JS教程08】数组及操作方法
    【JS教程07】事件属性及匿名函数
    【JS教程06】操作元素
    【JS教程05】获取元素的方法
    【JS教程04】条件语句
    多线程环境下非安全Dictionary引起的“已添加了具有相同键的项”问题
    GPT分区基础知识及如何在GPT分区上安装WIN7
    Jenkins TFS配置
    windows查看端口占用命令
    VS2015企业版序列号
  • 原文地址:https://www.cnblogs.com/JerryWang1991/p/3149759.html
Copyright © 2011-2022 走看看