C#调用C++生成的dll

1 新建工程

  (1)首先新建C#控制台工程,文件—新建—项目,选择控制台应用,如下图所示:
新建C#控制台
  (2)在此工程中添加C++的动态链接库项目,右键解决方案(注意这里是解决方案,不是C#工程),选择添加,选择新建项目,如下图:
添加工程
  (3)在添加新建项目的界面,选择VC++下面的Win32,然后选Win32项目,修改对应文件名称,如下图:
新建DLL

  (4)点击确定后进入设置向导,在应用程序类型中选择DLL,在附加选项中勾选导出符号和预编译头,点击确定即可(若熟练流程后,可自行添加文件,不勾选该选项)。
dll设置向导

  (5)开始编写代码。打开刚才添加的文件的,打开cpp和h文件如下图,这里是模板生成的文件,可根据需要删除,此处删除该模板生成的代码。

cpp文件 h文件
导出模板c 在这里插入图片描述

在CPPDLL.cpp文件写测试代码如下:

//cpp文件
int num = 0;

CPPDLL_API int getnum(void)
{
	return num;
}

CPPDLL_API void setnum(int n)
{
	num = n;
}

CPPDLL_API int intadd(int a, int b)
{
	int tmp = a + b;
	return tmp;
}

在CPPDLL.h文件写测试代码如下:

#ifdef CPPDLL_EXPORTS
#define CPPDLL_API __declspec(dllexport)
#else
#define CPPDLL_API __declspec(dllimport)
#endif


CPPDLL_API int intadd(int a, int b);
CPPDLL_API int getnum(void);
CPPDLL_API void setnum(int n);

点击生成解决方案,即可生成dll。使用Dependency Walker打开该dll文件,查看生成的dll中的函数
查看dll

2 联合调试

  在上一步中将dll完成后,现在来写Csharp的测试程序,程序如下:
在命名空间中加入下面这句话,表示调用外部dll,使用DllImport

using System.Runtime.InteropServices;

主程序如下:

   class Program
    {
        [DllImport("CPPDLL.dll", EntryPoint = "intadd", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false)]
        public extern static int intadd(int a, int b);
        [DllImport("CPPDLL.dll", EntryPoint = "setnum", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false)]
        public extern static void setnum(int n);   
        [DllImport("CPPDLL.dll", EntryPoint = "getnum", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false)]
        public extern static int getnum();

        static void Main(string[] args)
        {
            int aa = 1, bb = 2;
            int cc = 5;
            Console.WriteLine(aa);
            Console.WriteLine(bb);
            Console.WriteLine(cc);

            var sum = intadd(aa, bb);
            Console.WriteLine(sum);

            cc = getnum();
            Console.WriteLine(cc);

            setnum(10);
            cc = getnum();
            Console.WriteLine(cc);

            Console.ReadLine();
        }
    }

联合调试前的准备:

  • 首先选择dll项目,右键–属性–常规,设置如下(注意标记的地方):
    CPP调试设置
    这里设置输出目录的原因是:在DllImport(“CPPDLL.dll”)时设置的是相对路径,即exe文件与dll文件在同一个文件夹下,也可以改为绝对路径,如DllImport(“E:\desktop\Csharp_demo\Csharp_demo\bin\Debug\CPPDLL.dll”),但不建议这么做,因为当生成的exe在其他电脑上运行时,这种情况下exe一般与dll在一个文件夹,使用相对路径更好,使用绝对路径可能会报错。

  • 然后选择C#控制台项目,右键–属性–调试,设置如下:
    C#设置

  • 接着就可以开始进入调试模式,先在需要调试的地方添加断点,然后点击生成解决方案(注意每次修改dll中的函数后,最好选择重新生成解决方案,以便更新生成的dll),然后点击启动即可进行调试。

设置断点 调试断点
cpp断点 调试断点

最后的调试结果如下:
测试结果

3 相关问题的总结

3.1 运行编译平台问题

  关于dll版本与C#控制台版本的问题。x86的dll在x86的C#控制台上肯定是可以运行的,x64同理。下面主要讨论,x86的dll在x64的C#控制台上是否可以运行以及x64的dll在x32的C#控制台上是否可以运行。
  首先测试dll为x64版本,将dll设置x64版本,然后选择C#工程,右键–属性–生成,找到目标平台,选择x86。测试对比,如下表所示:

平台 x64dll+x86C# x86dll+x64C#
设置 x64dll+x86C# x86dll+x64C#
结果 报错 运行正常

报错(其他信息:试图加载格式不正确的程序,异常来自HRESULT:0x8007000B)具体情况如下图:
x64dll+x86C#报错

  结论:x64的exe可以运行x86和x64的dll,但x86的exe只能运行x86的dll。因此使用动态链接的时候应特别注意版本,在发布的时候应用realease版本的dll。

3.2 运行环境问题

  当将本地生成的exe与dll在其他电脑上运行时,会出现如下错误:
找不到dll,错误代码0x8007007e
错误原因:该电脑未安装Visual C ++ 2015 Redistributable Packages(dll由VS2015编译,其他的找对应版本即可)
解决办法:
方法1、安装Visual C ++ 2105 Redistributable Packages组件
方法2、在编译dll之前,“项目属性–C/C+±-代码生成”,“运行库改”为“多线程(/MD)”;
“项目属性–链接器–系统”, “所需的最低版本”,修改为“5.01”。
踩过了许多坑,发现CSDN上面写的方法,好多都没效果,最后是google找到的。。。。

猜你喜欢

转载自blog.csdn.net/qq_18150255/article/details/89765045