【45】C#入门到精通——C#调用C/C++生成动态库.dll及C++ 生成动态库.dll ,DllImport()方式导入 C++动态库.dll方法总结

文章目录

  • [1 C++ 生成动态库.dll](#1 C++ 生成动态库.dll)
  • 2 C#调用C/C++生成动态库.dll
    • [2.1 [DllImport()] 方式导入 C++动态库.dll](#2.1 [DllImport()] 方式导入 C++动态库.dll)
    • [2.2 调用测试](#2.2 调用测试)
  • [3 C/C++ 生成通用dll,改进](#3 C/C++ 生成通用dll,改进)
  • [4 [DllImport()] 方式导入C++生成的 .dll 总结](#4 [DllImport()] 方式导入C++生成的 .dll 总结)
    • [4.1 指定路径导入](#4.1 指定路径导入)
    • [4.2 .dll放在 执行目录下(一定要放对)](#4.2 .dll放在 执行目录下(一定要放对))

C#动态调用DLL文件(有的DLL是用C++或其它语言写的不能直接调用,但可以用态调用)
C#【必备技能篇】VS2019 使用C/C++ 生成DLL 文件,并用 C/C++、C#调用DLL

1 C++ 生成动态库.dll

C++ 生成动态库.dll 详细教程:C++ 生成动态库.dll 及 C++调用DLL,C++ 生成静态库.lib及 C++调用lib

教程中如图,声明了三种类型的函数;

  • 导出函数
  • 导出类函数
  • 以C方式导出函数 注: 只有这种方式才可被 C#调用

下面就用C# 试图调用这三种类型的函数:

2 C#调用C/C++生成动态库.dll

新建 C# windows窗体应用(.NET Framework)项目

试图通过 引用的方式 引用C/C++生成动态库.dll报错,因为这种方式只能 引用C#生成的动态库dll

2.1 [DllImport()] 方式导入 C++动态库.dll

建好 windows窗体应用(.NET Framework)项目后,

找到项目中Form1.cs双击弹出 类似于 MFC的窗口,在右侧拖一个button,

双击进入button函数,写调用 C++动态库.dll中函数的实现代码

  • 在button函数外面先导入,C/C++动态库.dll中的函数名
c 复制代码
//导入函数
        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int add(int a, int b);

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll", EntryPoint = "subtract")]
        static extern int subtract(int a, int b);

        //导入类函数
        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll", EntryPoint = "multiply")]
        static extern int multiply(int a, int b);

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int divide(int a, int b);

        //extern C ,以C方式导入函数
        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int Cadd(int a, int b);

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int Csubtract(int a, int b);

2.2 调用测试

在button 函数中,调用函数

c 复制代码
        private void button1_Click(object sender, EventArgs e)
        {
           //调用函数

            //int sum = add(10,5);
            int sub = subtract(10,5);

            int mul = multiply(10,5); 
            int div = divide(10, 5); 

            int Csum = Cadd(10, 5);
            int Csub = Csubtract(10, 5);

            //显示函数计算结果

            //MessageBox.Show("导入函数" + sum.ToString());
            //MessageBox.Show("导入函数" + sub.ToString());

            //MessageBox.Show("导入类函数" + mul.ToString());
            //MessageBox.Show("导入类函数" + div.ToString());

            MessageBox.Show("extern C ,以C方式导入函数" + Csum.ToString());
            MessageBox.Show("extern C ,以C方式导入函数" + Csub.ToString());
        }

完整代码

c 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CdllTest2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //导入函数
        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int add(int a, int b);

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll", EntryPoint = "subtract")]
        static extern int subtract(int a, int b);

        //导入类函数
        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll", EntryPoint = "multiply")]
        static extern int multiply(int a, int b);

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int divide(int a, int b);

        //extern C ,以C方式导入函数
        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int Cadd(int a, int b);

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int Csubtract(int a, int b);

        private void button1_Click(object sender, EventArgs e)
        {
           //调用函数

            //int sum = add(10,5);
            int sub = subtract(10,5);

            int mul = multiply(10,5); 
            int div = divide(10, 5); 

            int Csum = Cadd(10, 5);
            int Csub = Csubtract(10, 5);

            //显示函数计算结果

            //MessageBox.Show("导入函数" + sum.ToString());
            //MessageBox.Show("导入函数" + sub.ToString());

            //MessageBox.Show("导入类函数" + mul.ToString());
            //MessageBox.Show("导入类函数" + div.ToString());

            MessageBox.Show("extern C ,以C方式导入函数" + Csum.ToString());
            MessageBox.Show("extern C ,以C方式导入函数" + Csub.ToString());
        }
    }
}

点击button后,运行报错 ,找不到函数入口点;

导出函数 、 导出类函数 都会报错"无法在。。。。找到。。函数的入口点"

extern C ,以C方式导入函数

调用结果 如下

c 复制代码
 int Csum = Cadd(10, 5);
 int Csub = Csubtract(10, 5);

3 C/C++ 生成通用dll,改进

为了使自己建的 C/C++ 库可 都可以被C#调用

使用 __cplusplus

  • 当C++代码时,__cplusplus 值为1;
  • 当C 代码时,__cplusplus 值为0;
c 复制代码
#ifdef __cplusplus 
.
.
.
#endif

3.1改进后.h

c 复制代码
//#pragma once
#ifndef MATHTEST_H
#define MATHTEST_H

//宏定义导出:
#ifndef MATHTEST_ //如果没有定义 MATHTEST_,就定义MATHTEST_API __declspec(dllexport)
#define MATHTEST_API __declspec(dllexport) //导出
#else
#define MATHTEST_API __declspec(dllimport) //导入
#endif


//动态链接MATHTEST_API库


//以C语言的方式导出函数
//extern "C",告诉编译器这里是C语言代码

#ifdef __cplusplus 
extern "C"
{
#endif

	MATHTEST_API int Cadd(int a, int b);     //加法
	MATHTEST_API int Csubtract(int a, int b);//减法
	MATHTEST_API int Cmultiply(int a, int b); //乘法
	MATHTEST_API int Cdivide(int a, int b);   //除法

#ifdef __cplusplus
}
#endif

#endif

当C++ 代码时,__cplusplus 值为1,那么源代码对应部分 等价于

c 复制代码
extern "C"
{
	MATHTEST_API int Cadd(int a, int b);     //加法
	MATHTEST_API int Csubtract(int a, int b);//减法
	MATHTEST_API int Cmultiply(int a, int b); //乘法
	MATHTEST_API int Cdivide(int a, int b);   //除法
}
#endif

当C 代码时,__cplusplus 值为0,那么源代码 对应部分 等价于;

#ifdef __cplusplus ...#endif 部分是没有执行的

c 复制代码
	MATHTEST_API int Cadd(int a, int b);     //加法
	MATHTEST_API int Csubtract(int a, int b);//减法
	MATHTEST_API int Cmultiply(int a, int b); //乘法
	MATHTEST_API int Cdivide(int a, int b);   //除法

3.2 .cpp

c 复制代码
#include "mathTest.h"

//加法
int Cadd(int a, int b)
{
	return a + b;
}

//减法
int Csubtract(int a, int b)
{
	return a - b;
}

//乘法
int Cmultiply(int a, int b)
{
	return a * b;
}

//除法
int Cdivide(int a, int b)
{
	return a / b;
}

3.2 C# 调用

c 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CdllTest2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //extern C ,以C方式导入函数
        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int Cadd(int a, int b);

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll", EntryPoint = "Csubtract")]
        static extern int Csubtract(int a, int b);//EntryPoint关键词,要不要都行

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll", EntryPoint = "Cmultiply")]
        static extern int Cmultiply(int a, int b);

        [DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
        static extern int Cdivide(int a, int b);

        private void button1_Click(object sender, EventArgs e)
        {
            //调用函数
            int Csum = Cadd(10, 5);
            int Csub = Csubtract(10, 5);

            int Cmul = Cmultiply(10, 5);
            int Cdiv = Cdivide(10, 5);

            //显示函数计算结果
            MessageBox.Show("extern C ,以C方式导入函数\n" 
                             + "\nCsum = " + Csum.ToString()
                             + "\nCsub = " + Csub.ToString()
                             + "\nCmul = " + Cmul.ToString()
                             + "\nCdiv = " + Cdiv.ToString());
        }
    }
}

4 [DllImport()] 方式导入C++生成的 .dll 总结

4.1 指定路径导入

c 复制代码
[DllImport(@"E:\C#\CdllTest2\CdllTest2\bin\Debug\Dll1.dll")]
static extern int Cadd(int a, int b);

4.2 .dll放在 执行目录下(一定要放对)

.dll放在 执行目录下bin下面的 Debug或Release下面

c 复制代码
[DllImport("Dll1.dll")]
static extern int Cadd(int a, int b);

注意,有4种情况:

如果是 Debug X64,那么 .dll就放在 \bin\x64\Debug下面

如果是 Release X64,那么 .dll就放在 \bin\x64\Release下面

如果是 Debug Any CPU,那么 .dll就放在 \bin\Debug 下面

如果是 Release Any CPU,那么 .dll就放在 \bin\Release 下面