C# 调用 C++ DLL 操作说明

(1)通过使用VS2008创建项目解决方案,在解决方案中新增C++工程(DLL)和C# 工程(客户端)【创建C++DLLC#工程的具体步骤在此不详细说明,请参照相 关文档】;

(2)编译C++DLL工程和C#客户端工程;

(3)编译通过后将DLL生成的扩展名为DllLib,以及编写DLL时使用到的头文件 (扩展名为.h)全部复制到C#客户端程序所在的Debug文件夹下面;

(4)打开C#客户端程序,新建类:MyDLL(该类名供C#客户端调用)

(5)在C#客户端程序中引入命名空间:using System.Runtime.InteropServices;【之所以引用该空间,是因为在调用DLL时需要用到C#中API的一些特性】

(6)在MyDll类中写所需要的函数,注意函数的前面应给该函数加一些特性,例如:

    [DllImport("web.dll", EntryPoint = "?sum@CSpecialThing@@QAEHGPADPAUnc_pro@@@Z", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]

    public static extern int sum(int FlibHndl, string cnctype, ref nc_pro nc_pro00);

    首先介绍一下DllImport中的几个参数的含义:

    1. EntryPoing指示要调用的DLL入口点的名称或序号。

      如果你的方法名不想与api函数同名的话,一定要指定些参数,例如:

      [DllImport("user32.dll", CharSet = Charset.Ansi, EntryPoint = "MessageBox")]

      public static extern int MsgBox(IntPtr hWnd, string txt, string caption, int type);

      在上面的例子中,我们可以看到,EntryPoint中似乎存在一引起乱码:"?sum@CSpecialThing@@QAEHGPADPAUnc_pro@@@Z",为什么会存在这样的乱码,  我们后面会继续介绍,在些先介绍一下我们可以看懂的几个符号的含义:

      Sum:这是我们在C++的DLL中定义的函数名称;

      CSpecialThing:这是我们在DLL中定义的类;

        nc_pro:这是函数中的参数。为什么只有一个呢?个人认为只有你的参数是特殊类型时(例如:struct,其它的类型可能也会这样,但我目前的项目中只用到了消结构体),才会需要这样调用。

      有人可能觉得是不是我们在参数中用到了“ref”,那么这个参数就会出现在这一堆乱码中,我可以肯定的讲,绝对不是。。。。。

      至于其余的符号,我也不知道是什么意思了。。。。。

      2. CharSet控制调用函数的名称版本及指示如何向方法封送string 参数。

      此字段被设置为CharSet值之一。如果 CharSet字段设置为Unicode,则氖 字符串参数在传递到非托管实现之前都被转成Unicode字符。这还导致向DLLEntryPoint的名称中追加字母“W”。如果此字段设置为Ansi,则字符串将转换成ANSI字符串,同时向DLLEntryPoint的名称中追加字母“A”。大多数Win32 API使用这种追加“W”或“A”的约定。

    3. CallingConvention指示向非托管实现传递方法参数时所用的CallConvention值

      CallingConvention.Cdecl:调用方清理规模。它使您能够调用具有var args的函数。

      CallingConvention.StdCll:被调用方法清理堆栈。它是从托管代码调用非托管函数的默认约定。

(7)完成以上操作步骤后,你就可以在C#中调用 C++编写的DLL了。

 

 注:

编写C++DLL头文件中用到的函数,一定要在DLL的类名与class标识符之间加入 __declspec(dllexport),否则你就需要在所有的函数头中加入这一行。例:

class __declspec(dllexport) CSpecialThing

{}

其它的内容我们后续再讲。

 

 

原文地址:https://www.cnblogs.com/jerrychenfly/p/1854420.html