• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

C#和C++混合编程开发示例(VS2022上调试通过)

C#使用过程中经常会遇到和C++联合开发的过程,通过C++编写动态库,封装成dll后再C#中调用,在此做个记录,并供后期查看

一、新建C#控制台项目

打开VisualStudio,新建一个C#控制台项目,项目名称HelloWorldTest

点击下一步,一个空的默认c#项目创建完成

二、创建C++库

在解决方案上右键--添加--新建项目,建一个C++动态链接库工程,输入项目名称TestDll

创建完成后如下,在源文件--右键--新建项--添加C++(.CPP文件),文件内容如下:

#include "pch.h"
#include "HelloDll.h"
#include<iostream>

void HelloWorld(char* name)
{
	std::cout << "Hello World " << name << std::endl;
}

int Test()
{
	return 123456;
}

int Add(int a, int b)
{
	return a + b;
}

C++库导出有两种方式,但是最好两种方式同时使用,据说第二种是为了防止名字错乱,

   1、以C语言接口的方式导出

在头文件--右键--新建项,然后新建HelloDll.h头文件,如下图

这种方法就是在函数前面加上 extern "C" __declspec(dllexport)

加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。

extern "C" __declspec(dllexport) void HelloWorld(char* name);
extern "C" __declspec(dllexport) int Test();
extern "C" __declspec(dllexport) int Add(int a,int b);

2、以模块定义文件的方式导出

在源文件上点击右键,选择添加-》新建项

然后选择代码-》模块定义文件

在HelloDll.def中输入

LIBRARY "HelloDll"

EXPORTS

HelloWorld @ 1 
Test @ 2
Add @ 3

EXPORTS下面就是要导出的函数,这里不需要添加分号隔开,直接换行就行。

编译,生成dll。这里需要注意的是,如果生成是64位的库,C#程序也要是64位的,否则会报错,下图中默认是首选32位,所以需要把首选32位前的√去掉

在C#项目中添加引用:同时把C#代码修改为:

因为要用到DllImport,所以先导入命名空间using System.Runtime.InteropServices;

注意:在DllImport导入C/C++编写的动态库时函数,可以加上一些约定参数,例如:

[DllImport(@"HelloDll.dll", EntryPoint = "Test", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]

CallingConvention = CallingConvention.Cdecl,来指定入口点的调用约定,否则有可能会 报错

因为C/C++编写的动态库默认的入口点约定为_cdecl,而VS默认调用动态库时的约定为_winapi

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

namespace DllTest
{
    internal class Program
    {
        [DllImport("HelloDll.dll")]
        public static extern void HelloWorld(string name);
        [DllImport("HelloDll.dll")]
        public static extern int Test();
        [DllImport("HelloDll.dll")]
        public static extern int Add(int a, int b);

        static void Main(string[] args)
        {
            Console.WriteLine(Test().ToString());
            Console.WriteLine(Add(2, 5));
            HelloWorld("LiLi");
            Console.ReadKey();
        }
    }
}

运行程序,结果如下:

这样就成功实现了C#调用的C++库


全部回复(41)
正序查看
倒序查看
米修儿
LV.4
2
2021-12-15 14:49

两种导出方式都可以正常运行,但是同事说最好两种导出方式同时都有,否则可能会出现名字混乱等未知情况,也欢迎大家一起讨论

0
回复
晨风
LV.1
3
2021-12-18 09:35

不错,受益匪浅

0
回复
2021-12-18 09:40

C#和C++还可以混合编程开发,长见识了

0
回复
十三猫
LV.1
5
2021-12-20 08:48

新视角,新的切入点,不错不错,跟着大神学习

0
回复
2021-12-20 12:27

有空也学习一下,要学的东西很多啊

0
回复
米修儿
LV.4
7
2021-12-20 16:45
@lihui710884923
C#和C++还可以混合编程开发,长见识了

最近也是有空,准备补习下C++,一起学习交流吧

0
回复
十三猫
LV.1
8
2021-12-20 20:24

C++库两种方式导出方式,平时也是习惯两种都写上

0
回复
2021-12-22 14:58

vs确实是宇宙最强大编辑器,没有之一,C++,python都能胜任

0
回复
dy-q1PtffAR
LV.1
10
2021-12-22 14:59

根据示例调试了一遍,顺利调试通过,学习了

0
回复
米修儿
LV.4
11
2021-12-22 15:01
@dy-q1PtffAR
vs确实是宇宙最强大编辑器,没有之一,C++,python都能胜任

是的,是的,没有VS干不了的事,现在新版本也是越来越强大了,但是占用资源也越来越大

0
回复
米修儿
LV.4
12
2021-12-22 15:02
@lihui710884923
有空也学习一下,要学的东西很多啊

有C基础,转入C++基本可以无缝对接

0
回复
米修儿
LV.4
13
2021-12-22 15:05
@lihui710884923
有空也学习一下,要学的东西很多啊

你是用C高手,转投C++so easy

0
回复
晨风
LV.1
14
2021-12-22 15:09

HelloWorld @ 1 

Test @ 2

Add @ 3   这个里面的标号是不是必须的,看有的程序里面没有标号

0
回复
米修儿
LV.4
15
2021-12-23 09:02
@晨风
HelloWorld@1 Test@2Add@3  这个里面的标号是不是必须的,看有的程序里面没有标号

我看很多教程上确实没有标号,但是看很多前辈的程序里面都有标号,不知道是因为这样更清晰还是因为需要

0
回复
2021-12-23 14:06

生成dll的时候,一定要记得跟C#选一样的X64为平台,或者去掉首选32位,要不调试报错

1
回复
dy-SLPHrVRz
LV.1
17
2021-12-23 15:30

看过C++一直没学好指针,文章写的通俗易懂,收藏了

0
回复
dy-SLPHrVRz
LV.1
18
2021-12-23 15:30

写的很详尽,遇到问题了过来一起讨论

0
回复
dy-SLPHrVRz
LV.1
19
2021-12-23 15:31

很不错的教程,正好需要,先马后看

0
回复
dy-SLPHrVRz
LV.1
20
2021-12-23 15:39

C#确实强大,开发Unity3D,开发C++真的是无所不能

0
回复
2021-12-23 15:45

先顺手收藏起来,等有问题方便过来查找讨论

0
回复
米修儿
LV.4
22
2021-12-23 16:04
@dy-SLPHrVRz
C#确实强大,开发Unity3D,开发C++真的是无所不能

是的,Vs是真的强大,宇宙最强编辑器

0
回复
米修儿
LV.4
23
2021-12-23 16:08
@星球居民-6wBTmHfM
生成dll的时候,一定要记得跟C#选一样的X64为平台,或者去掉首选32位,要不调试报错

我第一次调试的时候,虽然选了64位,但是忘了把首选32位去掉,结果编译错误

0
回复
米修儿
LV.4
24
2021-12-23 16:10
@dy-SLPHrVRz
看过C++一直没学好指针,文章写的通俗易懂,收藏了

不好学,但是很多人用的东西,一定有很多的过人之处,努力学习中

0
回复
米修儿
LV.4
25
2021-12-23 16:13
@dy-SLPHrVRz
很不错的教程,正好需要,先马后看

我也是边学习边记录,下次需要就好找了

0
回复
米修儿
LV.4
26
2021-12-23 16:22
@星球居民-6wBTmHfM
先顺手收藏起来,等有问题方便过来查找讨论

我也是边学习,边记录,也方便自己查看,顺便记录也是学习的过程

0
回复
米修儿
LV.4
27
2021-12-23 16:29
@星球居民-6wBTmHfM
先顺手收藏起来,等有问题方便过来查找讨论

对,先收藏,需要的时候好找,要不需要的时候找不到了

0
回复
#回复内容已被删除#
28
#回复内容已被删除#
29
dy-NCJU4yct
LV.1
30
2021-12-27 09:17

VS确实强大,竟然可以开发python,有空摸索一下

0
回复
dy-NCJU4yct
LV.1
31
2021-12-27 09:27

重新开始学习,把大学拉掉的再学会来

0
回复