C#调用C动态链接库
前言
已经没写过博客好久了,上一篇还是1年半前写的LTE Gold序列学习笔记,因为工作是做通信协议的,然后因为大学时没好好学习专业课,现在理论还不扎实,不敢瞎写;
因为工作原因,经常需要分析一些字节流数据,所以基本都是用C写的,结果输出在命令行,或者txt/csv文件;但个人还是喜欢输出到GUI界面,可选的手段就MFC、WinForm、PyQt:
MFC的话感觉多少有点过时了,所以用WinForm,PyQt的多点,尤其是WinForm很方便;前段时间用WinForm写了个日志分析工具,因为本人是业余的C#使用者,所以写的很痛苦,至于数据处理的核心思想就CSDN上的结构体字节流的相互处理,数据处理部分大概1000来行;但工作中用的结构体通常很大,涉及大小端转换,同时还有位域,处理起来很麻烦,用C的话就很方便,所以用C处理数据用WinForm、PyQt显示的方法比较方便;所以就想着用C处理玩数据保存到txt/csv文件,然后用C#/Python去调用C应用并读取文件,但感觉有点low;所以就打算把C部分的处理输出成dll文件,然后用C#/Python去调用DLL;当然对我的需求来说,把所有数据封装到1个结构体里面,每个结构体字段是Uint或者Uint数组即可;以下部分实现就仅仅是能用即可,没具体设置;
C语言部分-编译生成动态链接库
我办公电脑上是VS2015,自己电脑是VS2017,创建工程有点差异;
VS2015工程设置使用CSDN上面的截图,注意源文件后缀用默认的cpp,不要用c,我还没去学习这块的细节,反正能用就行

VS2017生成控制台应用程序后,需要将如下红框中的配置类型修改为动态库;

然后代码和C应用程序的差异的话就在函数声明或定义前加上
extern "C" _declspec(dllexport) int add_test(int x, int y);
不设置配置和平台的话,默认输出就在Debug路径下生成和项目名一样的DLL文件,如下图:

C#部分-使用动态链接库
把编译生成的DLL文件放到C#编译输出的路径下,不配置的话就在如下路径:

在C#中调用C的话,核心代码就如下2行,
[DllImport("DLLTEST.dll",CallingConvention=CallingConvention.Cdecl)]
extern static int add_test(int x, int y);
还有需要注意的点,需要包含如下引用,当然写了如上第一行就会提示让包含了:
using System.Runtime.InteropServices;
感觉像是函数外部声明,能用就行,暂时没有去深究原理啥的,输出如下:

因为需要处理的数据通常比较多,所以就定义一个结构体,把需要传输的数据全放里面,然后用1个接口就读过去了;
简单做个测试
- C程序定义一个结构体,结构体里面仅包含一个字段,字段是一个Uint类型的数组:
typedef struct
{unsigned int data[32];
}RetData;
- C程序输出结构体数据测试:
void get_array(RetData* ret)
{for (int idx = 0; idx < 32; idx++){ret->data[idx] = idx * 10;}
}
- C#程序也定义一个结构体,结构体包含一个字段,字段是Uint32类型的数组:
struct GetData{[MarshalAs(UnmanagedType.ByValArray,SizeConst =32)]public UInt32[] data;}
-
C#程序读入结构体数据测试,可能用法很不专业,能读出来就行
/* 函数外部声明 */
[DllImport("DLLTEST.dll", CallingConvention = CallingConvention.Cdecl)]
extern static void get_array(ref GetData ret);/* 在Main函数中调用 */
GetData getData = new GetData();
get_array(ref getData);
- 输出

今天下午在公司写了个维测工具,整个流程和上面测试步骤一致,能正常使用
Python部分-使用动态链接库
把编译生成的DLL文件放到Python文件同级路径下,这样在Python代码中就直接使用DLL文件名即可,Python测试代码如下,调用数组那块先前在公司测试正常能用来自,忘了,懒得写了
import ctypes
dll = ctypes.windll.LoadLibrary('DLLTEST.dll')
print(dll.add_test(4, 5))
输出5:如下图:

本来打算把整个工程打包放到CSDN来着,但免费的话审核不通过,所以就把C/C#部分代码都贴下面了:
C程序头文件
#pragma once
#ifndef DLL_TEST_H
#define DLL_TEST_Htypedef struct
{unsigned int data[32];
}RetData;extern "C" _declspec(dllexport) int add_test(int x, int y);
extern "C" _declspec(dllexport) void get_array(RetData* ret);#endif // !DLL_TEST_H
C程序源文件
#include <stdio.h>
#include <stdlib.h>
#include "dll_test.h"int add_test(int x, int y)
{return x + y;
}void get_array(RetData* ret)
{for (int idx = 0; idx < 32; idx++){ret->data[idx] = idx * 10;}
}
C#程序
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApp1
{struct GetData{[MarshalAs(UnmanagedType.ByValArray,SizeConst =32)]public UInt32[] data;}class Program{[DllImport("DLLTEST.dll",CallingConvention=CallingConvention.Cdecl)]extern static int add_test(int x, int y);[DllImport("DLLTEST.dll", CallingConvention = CallingConvention.Cdecl)]extern static void get_array(ref GetData ret);static void Main(string[] args){Console.WriteLine("{0} + {1} = {2}", 4, 5, add_test(4, 5));GetData getData = new GetData();get_array(ref getData);Console.ReadLine();}}
}
相关文章:
C#调用C动态链接库
前言 已经没写过博客好久了,上一篇还是1年半前写的LTE Gold序列学习笔记,因为工作是做通信协议的,然后因为大学时没好好学习专业课,现在理论还不扎实,不敢瞎写; 因为工作原因,经常需要分析一些字…...
前端实现转盘抽奖 - 使用 lucky-canvas 插件
目录 需求背景需求实现实现过程图片示意实现代码 页面效果lucky-canvas 插件官方文档 需求背景 要求实现转盘转动抽奖的功能: 只有正确率大于等于 80% 才可以进行抽奖;“谢谢参与”概率为 90%,“恭喜中奖”概率为 10%; 需求实现 实…...
2024.1.23力扣每日一题——最长交替子数组
2024.1.23 题目来源我的题解方法一 枚举 题目来源 力扣每日一题;题序:2765 我的题解 方法一 枚举 每次都以两个相邻作为满足要求的循环数据,并且以一个布尔变量控制循环的位置 时间复杂度:O(n) 空间复杂度:O(1) pub…...
C语言王道练习题第七周两题
第一题 Description 输入一个学生的学号,姓名,性别,用结构体存储,通过 scanf 读取后,然后再 通过 printf 打印输出 Input 学号,姓名,性别,例如输入 101 xiongda m Output 输出…...
某马头条——day11+day12
实时计算和定时计算 流式计算 kafkaStream 入门案例 导入依赖 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-streams</artifactId><exclusions><exclusion><artifactId>connect-json</artifactId&…...
springboot实现aop
目录 AOP(术语)引入依赖实现步骤测试验证感谢阅读 AOP(术语) 连接点 类里面哪些方法可以增强,这些点被称为连接点 切入点 实际被真正增强的方法 通知(增强) 实际增强的逻辑部分称为通知(增强) 通知(增强&…...
Golang 中高级工程师学习笔记
闭包的作用 闭包(Closure)是一种函数值,它可以引用在其外部定义的变量。闭包允许这些变量保持在函数内部,而不是被每次调用时重新创建。闭包的作用主要体现在以下几个方面 封装: 闭包允许函数访问其外部作用域中的变…...
USB-C接口给显示器带来怎样的变化?
随着科技的不断发展,Type-C接口已经成为现代电子设备中常见的接口标准。它不仅可以提供高速的数据传输,还可以实现快速充电和视频传输等功能。因此,使用Type-C接口的显示器方案也受到了广泛的关注。本文将介绍Type-C接口显示器的优势、应用场…...
写一份简单的产品说明书:格式和排版建议
现在的市场竞争那么激烈,拥有一份简洁明了的产品说明书可以说是很重要的。产品说明书不仅向用户提供了对产品的详细了解,还能够树立品牌形象,提升用户体验。 | 一、写一份简单的产品说明书—一些建议 1.创意封面设计 一个吸引人的封面设计能…...
【Python学习】Python学习21- 正则表达式(1)
目录 【Python学习】Python学习21- 正则表达式(1) 前言re.match函数实例 re.search方法re.match与re.search的区别参考 文章所属专区 Python学习 前言 本章节主要说明Python的正则表达式。 正则表达式是一个特殊的字符序列,它能帮助你方便的…...
Docker 和 Kubernetes:容器化时代的崛起与演变
在过去的十年间,容器化技术彻底改变了软件开发和部署的面貌。 Docker 的登场无疑是这场变革的催化剂,它将应用和服务的打包、分发、部署流程标准化,让开发者的生活变得更加简单。 紧随其后,Kubernetes 作为容器编排的领军者&#…...
美易官方京东养车回应索赔事件:推动行业健康发展并携手品牌商家加码补贴
近日,一则关于途虎养车起诉京东索赔500万元的新闻引起了业界的广泛关注。据华尔街见闻1月25日报道,针对此事,京东养车相关负责人作出了回应。京东养车表示,“震虎价”并非针对特定企业,其核心目的在于通过提升效率来改…...
深度学习与图像描述生成——看图说话(3)
目录 一、整体架构 二、学习策略 2.1 监督学习 2.2 无监督学习 2.3 强化学习 三、特征映射 3.1 定义 3.2 原理 3.3 关键技术 3.4 重要案例 3.5 特别注意下特征空间这一概念 四、语言模型 4.1 定义与原理 4.2 关键技术 4.3 重要性与作用 4.4 案例与应用 五、注…...
[SAP ABAP] ABAP编程中SY-SUBRC值的含义
在ABAP编程中,SY-SUBRC是一个系统变量,用于表示最近一次执行的系统命令(例如数据库操作、函数模块调用等)的结果状态码 SY-SUBRC的值用于检查命令是否执行成功,通常用于控制程序的流程 查询数据 使用SELECT语句选择查询 SY-SUBRC 0 &qu…...
测试模型分类
测试模型 1. 概述 软件测试和软件开发一样,都遵循软件工程原理,遵循管理学原理,所以理解好软件的开发模型会便于理解测试模型. 软件测试的一般流程: 我们发现一般的软件测试流程和软件开发的流程一样,但是这样的流程测试介入的较晚,对于前期重大的bug很难修复.所以测试的流程…...
mavros和PX4中的海拔高与椭球高转换
飞控高度传感器中一般有两种高度: 海拔高。也称AMSL(Above Mean Sea Level)height或者geoid height或者正高,顾名思义就是指高于当地平均海平面的高度。我猜气压计测得的高度应当就是与海平面相关的。椭球高。也称ellipsoid heig…...
洛谷刷题-【入门2】分支结构
目录 1.苹果和虫子 题目描述 输入格式 输出格式 输入输出样例 2.数的性质 题目描述 输入格式 输出格式 输入输出样例 3.闰年判断 题目描述 输入格式 输出格式 输入输出样例 4.apples 题目描述 输入格式 输出格式 输入输出样例 5.洛谷团队系统 题目描述 …...
文件包含技术总结
开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这中文件调用的过程一般被称为文件包含。 allow_url_fopen On(是否允许打开远程文件) allow_url_include On&…...
Docker搭建私有仓库
Docker搭建私有仓库 下载docker registry镜像 docker pull docker.io/registry2.registry镜像下载完成后,先创建一个存放镜像的目录。 mkdir -p /data/registry3.启动registry容器 docker run -itd -p 5000:5000 -v /data/registry:/var/lib/registry docker.io…...
【计算机网络】【练习题】【新加坡南洋理工大学】【Computer Control Network】
说明: 仅供学习使用。 一、题目描述 该题目描述一个网络中传播时延(Transmission Delay)的例子。题目如下: 二、问题解答(个人) 笔者第3问采用均值不等式求解。标答中采用求导数的方法求极值。似乎均值…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
