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

      最近工作需要使用C#调用DLL,公司代码不能公开就转载加一些自己的笔记记录一下。使用软件VS2008和VS2017。

    1 C#静态调用DLL

    1.1  建立VC工程CppDemo,建立的时候选择Win32 Console(dll),选择Dll。

    1.2  在DllDemo.cpp文件中添加这些代码。

    extern "C" __declspec(dllexport) int Add(int a,int b)
    {
        
         return a+b;
    }
    View Code

    1.3 编译工程。

    1.4 建立新的C#工程,选择Console应用程序,建立测试程序InteropDemo
    1.5 在Program.cs中添加引用:using System.Runtime.InteropServices;

    1.6 在pulic class Program添加如下代码:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;   // 用 DllImport 需用此 命名空间
    
    namespace InteropDemo
    {
        class Program
        {
            [DllImport("CppDemo.dll", EntryPoint = "Add", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
            public static extern int Add(int a, int b); //DllImport请参照MSDN
    
            static void Main(string[] args)
            {
                Console.WriteLine(Add(1, 2));
                Console.Read();
            }
        }
    }    
    View Code

    2 C#动态调用DLL

    在第一节中,讲了静态调用C++动态链接,由于Dll路径的限制,使用的不是很方便,C#中我们经常通过配置动态的调用托管Dll,例如常用的一些设计模式:Abstract Factory, Provider, Strategy模式等等,那么是不是也可以这样动态调用C++动态链接呢?只要您还记得在C++中,通过LoadLibrary, GetProcess, FreeLibrary这几个函数是可以动态调用动态链接的(它们包含在kernel32.dll中),那么问题迎刃而解了,下面我们一步一步实验

    2.1 将kernel32中的几个方法封装成本地调用类NativeMethod

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace InteropDemo
    {
        public static class NativeMethod
        {
            [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
            public static extern int LoadLibrary(
                [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
    
            [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
            public static extern IntPtr GetProcAddress(int hModule,
                [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
    
            [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
            public static extern bool FreeLibrary(int hModule);
        }
    }
    View Code

    2.2 使用NativeMethod类动态读取C++Dll,获得函数指针,并且将指针封装成C#中的委托。原因很简单,C#中已经不能使用指针了,如下          
                int hModule = NativeMethod.LoadLibrary(@"c:"CppDemo.dll");

                IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "Add");

    详细请参见代码 

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace InteropDemo
    {
        class Program
        {
            //[DllImport("CppDemo.dll", EntryPoint = "Add", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl)]
            //public static extern int Add(int a, int b); //DllImport请参照MSDN
    
    
            static void Main(string[] args)
            {
                //1. 动态加载C++ Dll
                int hModule = NativeMethod.LoadLibrary(@"c:CppDemo.dll");
                if (hModule == 0) return;
    
                //2. 读取函数指针
                IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "Add");
    
                //3. 将函数指针封装成委托
                Add addFunction = (Add)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(Add));
    
                //4. 测试
                Console.WriteLine(addFunction(1, 2));
                Console.Read();
            }
    
            /// <summary>
            /// 函数指针
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            delegate int Add(int a, int b);
    
        }
    }
    View Code

    3 注意事项:

    3.1 使用静态调用时必须将DLL文件和相关配置文件放于C#可执行文件同一部木之下,否则会报错;

    3.2 在C#中使用DllImport必须添加   using System.Runtime.InteropServices;

    3.3 C#调用DLL时需要将 Properties中平台目标 改为和生成DLL中平台一致。(一般生成dll都是Win32,所以平台目标要改为X86。)                                                    

      

    4 数据类型问题

    因为在C#中部使用非安全是没有指针数据类型,而一般使用C或C++制作的DLL,DLL中函数的参数列表会有指针类型,调用是就必须要解决或了解这一部分知识——互操作数。

    4.1 C#互操作性入门系列(一):C#中互操作性介绍

    4.2 C#互操作性入门系列(二):使用平台调用调用Win32 函数

    4.3 C#互操作性入门系列(三):平台调用中的数据封送处理

    4.4 C#互操作性入门系列(四):在C# 中调用COM组件

    转载链接:

    1) https://www.cnblogs.com/Jianchidaodi/archive/2009/03/09/1407270.html

     2)  https://www.cnblogs.com/zhili/archive/2013/01/14/NetInterop.html

  • 相关阅读:
    vim 高级使用技巧第二篇
    你所不知道的Html5那些事(一)
    linux设备驱动第三篇:如何实现一个简单的字符设备驱动
    Android Metro风格的Launcher开发系列第二篇
    「BZOJ3123」[SDOI2013]森林
    【模板】左偏树
    「luogu3157」[CQOI2011]动态逆序对
    「luogu3567」[POI2014]KUR-Couriers
    【模板】二逼平衡树
    「luogu3313」[SDOI2014]旅行
  • 原文地址:https://www.cnblogs.com/kwinwei/p/11920729.html
Copyright © 2011-2022 走看看