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

文章目录

  • 1 C++ 生成动态库.dll
  • 2 C#调用C/C++生成动态库.dll
    • 2.1 [DllImport()] 方式导入 C++动态库.dll
    • 2.2 调用测试
  • 3 C/C++ 生成通用dll,改进
    • 3.1改进后.h
    • 3.2 .cpp
    • 3.2 C# 调用
  • 4 [DllImport()] 方式导入C++生成的 .dll 总结
    • 4.1 指定路径导入
    • 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中的函数名
//导入函数[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 函数中,调用函数

        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());}

完整代码

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方式导入函数
调用结果 如下

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

在这里插入图片描述

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

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

使用 __cplusplus

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

3.1改进后.h

//#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"
{
#endifMATHTEST_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,那么源代码对应部分 等价于

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 部分是没有执行的

	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

#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# 调用

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 指定路径导入

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

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

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

[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 下面
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/93995.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93995.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从协议栈到ath12k_mac_op_tx的完整调用路径

文章目录 从协议栈到ath12k_mac_op_tx的完整调用路径 1. 整体架构概览 2. 详细调用路径分析 2.1 应用层到Socket层 2.2 协议层处理 2.3 网络设备层到mac80211 2.4 mac80211发送入口 2.5 mac80211核心发送处理 2.6 mac80211发送核心处理 2.7 mac80211发送调度 2.8 最终驱动调用 …

WPFC#超市管理系统(4)入库管理

入库管理7. 商品入库管理7.2 入库实现显示名称、图片、单位7.3 界面设计7.3 功能实现7. 商品入库管理 数据库中StockRecord表需要增加商品出入库Type类型为nvarchar(50)。C#中的数据库重新同步StockRecord表在Entity→Model中新建枚举类型StockType namespace 超市管理系统.E…

CSS 打字特效

效果图.wxml <view class"tips"><text>{{ tipsText }}</text><text class"tips-line">|</text> </view>.wxss .tips{padding: 50rpx 100rpx;font-size: 28rpx; } .tips-line{color: #ccc;animation: tips-line .5s al…

直播小程序 app 系统架构分析

一、引言 直播行业近年来发展迅猛&#xff0c;直播小程序和 APP 成为众多用户获取直播内容以及主播进行内容输出的重要平台。一个完善且高效的系统架构是支撑直播业务稳定运行、提供优质用户体验的关键。本文将详细剖析直播小程序 / APP 的系统架构&#xff0c;包括整体架构设计…

Vue常见题目

1. 什么是 Vue.js&#xff1f;它的核心特点是什么&#xff1f; Vue.js 是一个渐进式 JavaScript 框架&#xff0c;用于构建用户界面。它的核心特点包括&#xff1a; - 响应式数据绑定 - 组件化开发 - 虚拟 DOM - 指令系统 - 轻量级且易于集成 - 丰富的生态系统&#xff08;Vue…

ipynb文件直接发布csdn

第一步&#xff0c;下载markdown文件 file --> save and export notebook as --> markdown第二步&#xff0c;导入markdown文件 进入csdn发布文章界面&#xff0c;点击导入&#xff0c;选择第一步下载的markdown文件即可

广东省省考备考(第六十四天8.2)——判断推理(重点回顾)

判断推理&#xff1a;数量规律 错题解析解析解析解析解析解析解析标记题解析解析解析解析解析解析解析今日题目正确率&#xff1a;53% 判断推理&#xff1a;属性规律 错题解析解析解析解析解析解析标记题解析解析今日题目正确率&#xff1a;60%

【C++/STL】vector的OJ,深度剖析和模拟实现

vector在OJ中的使用 1.只出现一次的数字 class Solution { public:int singleNumber(vector<int>& nums) {int value 0;for(auto e : v) {value ^ e; }return value;} };2.杨辉三角 class Solution { public:vector<vector<int>> generate(int numRow…

衡石湖仓一体架构深度解构:统一元数据层如何破除数据孤岛?

一、数据融合的世纪难题典型困境二、衡石统一元数据层设计架构核心关键技术实现智能元数据发现自动构建跨源血缘关系动态查询重写 将标准SQL翻译为最优执行计划text Original: SELECT SUM(sales) FROM virtual_view Rewritten: [S3] SELECT SUM(amount) FROM crm_sales [My…

Windows 下 fping 指令使用指南

fping 作为一款强大的网络工具&#xff0c;能够同时向多个主机发送 ICMP 回声请求&#xff0c;相较于传统的 ping 命令&#xff0c;在处理大量主机时具有显著优势。 一、fping 简介​ fping 是 “fast pinger” 的缩写&#xff0c;它可以向一系列 IP 地址发送 ICMP 回声请求。…

代码随想录day52图论3

文章目录101. 孤岛的总面积102. 沉没孤岛103. 水流问题104.建造最大岛屿101. 孤岛的总面积 题目链接 文章讲解 #include<bits/stdc.h> using namespace std;int ans 0; // 记录不与边界相连的孤岛数量 int sum 0; // 当前孤岛的面积 bool flag false; /…

linux pip/conda 修改默认cache位置

1 pip pip cache默认在/home/{username}目录下&#xff0c;容易导致系统盘写满报错。查看pip cache位置pip cache dir假设移动pip cache目录到 /data/.cache/pip/cache&#xff0c;命令如下pip config set global.cache-dir /data/.cache/pip/cache2 conda 查看conda缓存位置c…

如何解决pip安装报错ModuleNotFoundError: No module named ‘seaborn’问题

【Python系列Bug修复PyCharm控制台pip install报错】如何解决pip安装报错ModuleNotFoundError: No module named ‘seaborn’问题 一、摘要 在使用 PyCharm 终端进行模块安装时&#xff0c;常常会遇到如下异常&#xff1a; ModuleNotFoundError: No module named ‘seaborn’…

(思维)洛谷 P13551 ももいろの鍵 题解

题意 爱莉给了你一个非负整数 nnn&#xff0c;你需要把 0,1,2,…,n0, 1, 2, \dots, n0,1,2,…,n 划分成若干组&#xff0c;满足每一组的按位与为 000。 划分的组不需要相邻。 你需要最大化划分组数并给出方案。 1≤T≤6001 \le T \le 6001≤T≤600&#xff0c;0≤n≤1050 \le n…

记录一次ESP32报错Guru Meditation Error: Core 1 panic‘ed (Double exception).

一、问题描述 需求&#xff1a; ESP32S3单片机&#xff0c;连接一个麦克风读取5s后&#xff0c;编码后发送到百度云进行语音识别。通过freertos框架&#xff0c;将任务放在核1中运行&#xff08;放在核0同样报错&#xff09; 问题&#xff1a; 在最后的发送语音数据中&#xff…

半导体物理复习

半导体物理导论第一章 半导体的电子状态

vi/vim跳转到指定行命令

在 vi/vim 中跳转到指定行有多种高效方法&#xff0c;以下是最常用的操作方式&#xff1a; 一、基础跳转&#xff1a;行号 命令命令模式下直接输入行号 按 Esc 切换到命令模式后&#xff0c;输入 :行号 并回车。例如&#xff0c;输入 :100 会直接跳转到第 100 行。使用 G 快捷…

智能落地扇方案:青稞RISC-V电机 MCU一览

在科技飞速发展的今天&#xff0c;智能家居已成为人们生活中不可或缺的一部分&#xff0c;而风扇作为夏日解暑的必备家电&#xff0c;其智能化升级也成为了行业发展的必然趋势。传统落地扇功能单一、操作不便&#xff0c;已难以满足现代消费者对便捷、舒适、节能生活的追求。在…

SQL 中 WHERE 与 HAVING 的用法详解:分组聚合场景下的混用指南

SQL中WHERE与HAVING的用法详解&#xff1a;分组聚合场景下的混用指南 1. WHERE与HAVING的基本区别 在SQL查询中&#xff0c;WHERE和HAVING都是用于过滤数据的子句&#xff0c;但它们的应用时机和作用对象有本质区别&#xff1a; WHERE子句&#xff1a;在分组前对原始数据进行过…

14 - 大语言模型 — 抽取式问答系统 “成长记”:靠 BERT 学本事,从文本里精准 “揪” 答案的全过程(呆瓜版-1号)

目录 1、什么是问答系统&#xff1f; 2、问答系统的核心工作流程 2.1、理解问题&#xff1a;把问题 “翻译” 成机器能懂的形式 2.2、 寻找答案&#xff1a;从信息中定位答案 2.3、生成答案&#xff1a;整理并输出结果 2.4、优化迭代&#xff1a;让系统更 “聪明” 3、主…