【教程】关于C#中调用Cpp编写的dll

dll文件
dll文件用的图片

前几天写了一篇文章,讲了如何建立dll以及如何调用dll,文章中使用的是C/C++,今天就说说怎么使用C#调用C++的dll。


首先建立一个C#工程。然后再原文件夹中的Debug文件夹中放入我们做好的dll,这里我们使用前一篇文章中建立的dll:“basic_dll.dll”,然后就是写代码。

在C#中如果要调用dll,就要using一个空间:System.Runtime.InteropServices,包含进来就好了。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

这里包含进了一些无关的东西,不用管它,我一建立工程就有这些了,懒得删-_-……

如果要载入dll,就要在声明方法之前加上


[DllImport("basic_dll.dll", EntryPoint = "add",CallingConvention = CallingConvention.Cdecl)]

其中,“basic_dll.dll”是我们要引入的dll的名字,要么它在程序的同一目录下,要么在系统中已经注册过,后面的“EntryPoint”是dll的入口函数,也就是我们要导入的函数名称,再后面的CallingConvention是调用约定,如果不加上这个调用约定的话,会导致编译时出现”对 PInvoke 函数“xxFunction()”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配“这样的错误,原因一会说。

然后的然后就是声明一下我们的函数了,在这里同样只有一个add(int, int)   -_-

一下是一段简单到要死的源代码


namespace Csharp调用
{

class Program
{
[DllImport("basic_dll.dll", EntryPoint = "add",CallingConvention = CallingConvention.Cdecl)]
public static extern int add(int a, int b);

static void Main(string[] args)
{
Console.WriteLine(add(3, 5));
Console.ReadKey();
}
}
}

这段代码极其简单以至于我就跳过解读了,然后说说关于刚才提到的堆栈不对称的问题。

众所周知,在c++WIN32程序中有三种calling convention(调用约定):__cdecl, __stdcall, __fastcall,默认为__cdecl。而c#中默认为CallingConvention =CallingConvention.Winapi,如果不对调用约定进行说明的话,会出现调用约定不一致的错误。当然,在dll中,要传出的方法应该放在extern ”C“中,不然会因为C++更改函数名而导致调用错误。