C++复杂结构体的C#封装

C/Cpp过渡到C#的简易教程1 很迷幻啊,大学一直做MCU,也学C/Cpp,python,幻想过有一天能成为一名后端程序员,但是其实没抱太大希望,秋招找工作也是一直找的MCU/Linux方向。没想到最后也拿了个后端的offer,不过Linux还得做,offer上直接给我整了个嵌入式全栈,还挺看得起我233。不过要学的就多了,由于公司是做工业物联网,当前了解到的主要解决方案就是在win上开发ASP.NET,然后迁移到Linux环境下去。嵌入式全栈可不能松懈,好好学习,提高学习能力,项目中才能事半功百。于是我得改掉往日的风格,基础的一些太语. 阅读详情

对于一些比较复杂的C++结构体在封装成C#的时候要注意保持C++结构变量字节与C#结构体字节的对齐。

C++结构体示例:

 

typedef struct{

        e_float64              FontSize;                      // 字体大小

        e_float64              Angle;                         // 角度

        e_int32                FontColor;                     // 文本颜色

        e_int32                BackColor;                     // 文本背景色

        e_int32                Transparent;                   // 背景是否透明

        e_int32                Bold;                          // 文本粗体

        e_int32                Italic;                        // 文本斜体

        e_int32                Underline;                     // 文本下划线

        e_int32                XOffset;                       // 文本X偏移

        e_int32                YOffset;                       // 文本Y偏移

        e_int8                 FontName[128];         // 字体

}FONT_INFO_T;


 

C#封装的时候要注意保持C#的使用习惯,如上结构体,Transparent、Bold、Italic、Underline属性,在C#中一般则直接封装成bool类型,而这样封装则无法保存C++和C#结构的字节对齐,因此还需要一个中间转 换的结构体,这个转换结构体与C++结构体则必须完全保持一致,C#外部使用结构体与转换结构体又存在着一个转换,因此,封装出来的结构体必须要提供转换 方法。

先定义一个转换结构体,如下:

  [StructLayout(LayoutKind.Sequential)]

    internal struct Inner_HdFont

    {

        public double FontSize;                      // 字体大小

        public double Angle;                         // 角度

        public int FontColor;                 // 文本颜色

        public int BackColor;                 // 文本背景色

        public int Transparent;               // 背景是否透明

        public int Bold;                             // 文本粗体

        public int Italic;                           // 文本斜体

        public int Underline;                 // 文本下划线

        public int XOffset;                   // 文本X偏移

        public int YOffset;                   // 文本Y偏移

       [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]

        public string FontName;               // 字体

    }



C#最终定义结构体如下:

 

    ///<summary>

    /// 字体格式

    /// </summary>

    public struct HdFont

    {

        ///<summary>

        /// 字体大小

        ///</summary>

        public double Size;

        ///<summary>

        /// 角度

        ///</summary>

        public double Angle;

        ///<summary>

        /// 文本颜色0xbbggrr

        ///</summary>

        public int Color;

        ///<summary>

        /// 文本背景色0xbbggrr

        ///</summary>

        public int BackColor;

        ///<summary>

        /// 背景是否透明

        ///</summary>

        public bool Transparent;

        ///<summary>

        /// 文本粗体

        ///</summary>

        public bool Bold;

        ///<summary>

        /// 文本斜体

        ///</summary>

        public bool Italic;

        ///<summary>

        /// 文本下划线

        ///</summary>

        public bool Underline;

        ///<summary>

        /// 文本X偏移

        ///</summary>

        public int XOffset;

        ///<summary>

        /// 文本Y偏移

        ///</summary>

        public int YOffset;

        ///<summary>

        /// 字体

        /// </summary>

        public string Name;

 

        ///<summary>

        /// 将结构体转为非托管对象使用,外部申请内存和释放内存

        ///</summary>

        ///<param name="handle"></param>

        public IntPtr GetFontHandle()

        {

            Inner_HdFont inner_font = new Inner_HdFont();

            inner_font.Angle = Angle;

            inner_font.BackColor = BackColor;

            inner_font.Bold = (Bold == true ? 1 : 0);

            inner_font.FontColor = Color;

            inner_font.FontName = Name;

            inner_font.FontSize= Size;

            inner_font.Italic = (Italic == true ? 1 : 0);

            inner_font.Transparent = (Transparent == true ? 1 : 0);

            inner_font.Underline = (Underline == true ? 1 : 0);

            inner_font.XOffset = XOffset;

            inner_font.YOffset = YOffset;

            IntPtrhandle = Marshal.AllocHGlobal(Marshal.SizeOf(inner_font));

            Marshal.StructureToPtr(inner_font, handle, false);

            return handle;

        }

 

        ///<summary>

        /// 将非托管指针转换为结构体

        ///</summary>

        ///<param name="handle"></param>

        public void FromHandle(IntPtr handle)

        {

           Inner_HdFont inner_font = new Inner_HdFont();

           inner_font = (Inner_HdFont)Marshal.PtrToStructure(handle,typeof(Inner_HdFont));

            Angle =inner_font.Angle;

           BackColor = inner_font.BackColor;

            Bold =inner_font.Bold > 0 ? true : false;

            Color =inner_font.FontColor;

            Name =inner_font.FontName;

            Size =inner_font.FontSize;

            Italic= inner_font.Italic > 0 ? true : false;

           Transparent = inner_font.Transparent > 0 ? true : false;

           Underline = inner_font.Underline > 0 ? true : false;

            XOffset= inner_font.XOffset;

            YOffset= inner_font.YOffset;

        }

 

        ///<summary>

        /// 释放非托管内存

        ///</summary>

        ///<param name="hFont"></param>

        public static void ReleaseFontHandle(IntPtr hFont)

        {

            Marshal.FreeHGlobal(hFont);

        }

    };


 

对于这样的结构体传参需要特别注意,因为封装了一个内部结构体作为模块内部转换使用,因此,在封装API的时候参数类型必须使用指针类型,而不能直接使用结构,因为内部转换结构体才是和C++原始结构体对应的,而内部转换结构体主要作用是用来数据转 换,不向外部公布,若是使用向外面公开的C#结构体则由于与C++结构体不能对应,导致出错。

C#指针参数类型使用IntPtr,C++ 参数类型使用FONT_INFO_T*。

 

 

C#调用C++ DLL完整指南:P/Invoke方案与工程化实践 在软件开发中,动态链接库(DLL)是实现代码复用和模块化的重要技术,它允许不同编程语言编写的模块相互调用。其核心原理是通过预定义的二进制接口,实现跨语言函数调用和数据交换。这一技术价值在于能够充分发挥各语言优势,例如结合C#的高开发效率和C++的底层性能。在图像处理、音视频编解码、系统级编程等对性能要求较高的应用场景中,通过C#调用C++ DLL成为常见解决方案。本文以P/Invoke技术方案为例,详细解析了从项目创建、接口设计到内存管理和调试的完整实现流程,涵盖了数据类型映射和资源释放等关键工程实践,帮助 阅读详情

相关推荐

C#调用C++ DLL完整指南:从P/Invoke原理到生产环境避坑

在软件工程实践中,托管代码与非托管代码的互操作是连接不同技术生态的关键桥梁。其核心原理在于通过平台调用服务(P/Invoke)机制,实现.NET托管环境与原生C++运行时之间的数据封送与函数调用。这项技术的核心价值在于能够复用经过验证的高性能C++遗留代码库,或在C#应用中嵌入对计算性能、硬件驱动有极致要求的模块,从而兼顾开发效率与执行性能。典型的应用场景包括集成数学计算库、音视频处理引擎、硬件设备SDK以及游戏逻辑模块等。本文将深入解析C#与C++互操作时面临的**内存管理**挑战与**调用约定**匹配等

weixin_30940783的博客 695

C#调用C++封装的SDK库(dll动态库)——上

要把VS创建的DLL动态库,给C#代码来调用(并且我的动态库中还包含我的计算类)C#调用C++封装的SDK库(dll动态库)本篇文章就介绍如何来封装,并提供调用。但是,我遇到了一个场景:需要把VS创建的DLL动态库,给C#代码来调用(并且我的动态库中还包含我的计算类)。本篇文章就介绍如何来封装,并提供调用。

ifeng12358的博客 3623

Habitat-baselines v0.1.7防踩坑手把手带你跑通(全网唯一)

Habitat-baselines v0.1.7防踩坑手把手带你跑通(全网唯一)

shannanshouyin的博客 1276

c# 使用c++封装类库调用方式 (通过dll方式使用)

什么是托管代码?

leo`s home 4228

STM32 ST-LINK Utility固件烧录全流程详解与实战技巧

本文详细解析了使用STM32 ST-LINK Utility进行固件烧录的全流程与实战技巧。从硬件连接、软件安装、核心三步操作(连接、擦除、烧录)到进阶的选项字节配置与批量脚本烧录,提供了完整的避坑指南和问题排查方案,帮助开发者高效完成STM32程序下载。

lambda的博客 768

Splunk CVE-2018-11409认证绕过漏洞深度解析

Splunk作为主流企业级日志分析平台,其Web管理接口的认证机制直接关系到整个安全运营体系的可信边界。CVE-2018-11409本质上是REST API路由层会话校验缺失引发的未授权访问问题,根源在于`/en-US/splunkd/__raw/`路径绕过了splunkweb与splunkd之间的信任链验证,导致配置文件、用户哈希、App源码等敏感信息明文泄露。该漏洞凸显了Web接口权限模型设计失守的风险,尤其在默认配置未加固、HTTPS未启用、初始密码未修改的生产环境中危害急剧放大。结合vulfocus

weixin_30875157的博客 598

C#dll封装为c++接口

C#dll封装为c++接口

Jane_Yih的博客 1463

基于wxWidgets框架,使用DialogBlocks建立OpenGL界面

前言 之前公司要求使用wxWidgets做GUI,基于OpenGL图形内核,开发三维可视化工具。目前初步开发工作基本已经完成,剩下都是完善了。这里记录一下最开始的框架搭建过程(当然是简化版啦)。wxWidgets结合OpenGL开发可以实现跨平台应用,再结合CMake和VS Code,整体开发工具用习惯了会感觉非常顺手。 界面编辑 首先,使用DialogBlocks新建一个工程,这里工程目录...

cyberobot的博客 2750

c++ c#结构体调用

1、最近做项目遇到,C#调用C++dll里的函数需要传递结构体参数,发现这个并不是简单的在C#里定义相应的结构体就可以的,下面以一个例子来说明解决的办法,C++中的函数和结构体如下: uint msec_set_igr_gen_cfg(int port, IGR_GEN_T *igr_gen) { return 0; } typedef struct {   i

千愚千寻 6573

【Proteus】NE555纯硬件实现LED呼吸灯效果,附源文件,效果展示

本设计通过NE555与三极管的巧妙配合,仅用基础元件实现了呼吸灯效果。核心在于利用RC积分电路将PWM信号转换为控制电压,并通过负反馈动态调节占空比。Proteus仿真验证了方案的可行性,读者可进一步优化参数或扩展功能,探索更多硬件设计可能性。

2201_75797484的博客 2980

舵机PWM信号转互斥继电器开关信号

-----------------本文由“麦粒电子”撰写,并提供相应产品服务。---------------- 叙述 上次的PWM转继电器开关方案得到大家的不少好评(博客链接),但是发现有些玩家需要一路PWM同时去控制两路继电器开关通断,并且两者是互斥的,好去控制两种不同的负载。所以就继续升级了如下的模块。 正常的控制部件顺序这样:遥控器按钮拨动,遥控器接收机相应通道PWM值变化,PWM转开关模块检测PWM值发生变化从而驱动相应机械继电器触点吸合释放。本模块的两个继电器动作是互斥的,也就是不会同时吸合。

Mai_LiElectronic的博客 1631

C#调用C/C++动态库,封装各种复杂结构体。

现在公司要做一个使用C

liguo9860的专栏 2万+

《网络安全自学教程》- OSI七层模型分层及作用,数据封装与解封过程,数据传输过程。

OSI分哪七层,每层的作用是什么,解释数据在七层模型中是怎样传输的,封包和解封过程,数据包在每一层是怎么封装和解封的。

wangyuxiang946的博客 1万+

C#调用C++DLL传递结构体数组的终极解决方案

在项目开发时,要调用C++封装的DLL,普通的类型C#上一般都对应,只要用DllImport传入从DLL中引入函数就可以了。但是当传递的是结构体、结构体数组或者结构体指针的时候,就会发现C#上没有类型可以对应。这时怎么办,第一反应是C#也定义结构体,然后当成参数传弟。然而,当我们定义完一个结构体后想传递参数进去时,会抛异常,或者是传入了结构体,但是返回值却不是我们想要的,经过调试跟踪后发...

diansangjia3779的博客 651

手把手教你学Simulink——高频隔离型双向DC-AC逆变器的建模与仿真

本文系统讲解高频隔离型双向DC-AC逆变器的Simulink建模与仿真,基于DAB+全桥逆变两级拓扑,详述DAB移相控制原理、双闭环控制策略及分步仿真搭建流程。重点涵盖电路建模、控制环设计、参数设置与常见问题调试,强调模块化分步验证与分层控制逻辑,实现安全、高效、灵活的双向能量流动仿真,适用于储能、微电网等场景的系统开发与验证。

MHD0815的博客 107

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C#调用C++ 结构体方法

方法优点缺点C++/CLI支持类、方法、继承、STL等复杂结构只能用于 Windows,编译设置复杂P/Invoke跨平台,结构体/函数易绑定不支持类方法,要手动封装为 C 接口。

u013401364的博客 1219

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C# 调用 opencv 写的C++函数接口实现方法

C# 调用 C++ 函数实现方法 C# 调用 C++ 函数比较复杂的是结构体的封装,一般数据类型可以简单地转换为C# 的数据类型即可,对于结构体类型的传递或者是结构体中包含指针,结构体嵌套传递都会比较复杂、 结构体传递的方法例子: C# 函数封装C++ 结构体 参考 https://blog.youkuaiyun.com/sdl2005lyx/article/details/6801113 图像二值化...

u010796650的博客 705

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C#与C/C++ dll之间数据传递的一些问题与解决

目前因为工作原因需要使用WPF制作用户界面,同时对于处理算法方面需要使用C/C++来写算法并封装成Dll,以便C#端可以调用使用,对于常用类型,比如int,void,char等类别的传递因为之前使用过所以还算驾轻就熟,后面应用到了复杂点的结构体。例如结构体如下:C部分的typedef struct ErrorArea {//the closed rectangle area which conta...

zhilongqu0743的博客 770

C#和C++的数据封装_wind_新浪博客

C#和C++的数据封装 概念 在托管代码中对非托管函数进行互操作,需要对参数和返回值进行数据传递的过程,此过程有CLR的封送处理服务(封送拆送器)完成。其工作内容如下: 1.将数据从托管类型转换为非托管类型,或从非托管类型转换为托管类型; 2.将经过类型转换的数据从托管代码内存复制到非托管内存,或从非托管内存复制到托管内存; 3.调用完成后,释放封送处理过程中分...

石头王 159

C#调用带结构体指针的C Dll的方法【转】

发现一篇文章关于C#调用DALL动态链接库的函数的,复制下来学习用。感谢作者的分析,原文传送门:https://www.cnblogs.com/ye-ming/p/8004314.html 在C#中调用C(C++)类的DLL的时候,有时候C的接口函数包含很多参数,而且有的时候这些参数有可能是个结构体,而且有可能是结构体指针,那么在C#到底该如何安全的调用这样的DLL接口函数呢?本文将详细介绍如何...

weixin_30477293的博客 152

C#调用C++动态库的7种经典场景及解决方案(含源码级剖析)

掌握C#调用C++动态链接库(DLL)方法的7种经典场景与解决方案,涵盖字符串传递、回调函数、内存管理等核心问题,深入源码剖析互操作关键技术,提升开发效率,值得收藏。

PixelIsle的博客 1156

C#调用C++ DLL实战指南:原理、方法与避坑技巧

在软件工程实践中,托管代码与非托管代码的互操作是突破性能瓶颈、复用历史资产的关键技术。其核心原理在于跨越.NET CLR与原生运行时的边界,通过平台调用(P/Invoke)机制实现函数与数据的交互。这一过程涉及关键的数据封送(Marshaling)技术,负责在托管与非托管内存间转换数据类型,确保双方能正确理解彼此的数据结构。掌握互操作技术能有效解决计算密集型任务、硬件驱动集成或复用现有C++库等场景下的性能与生态难题。本文以C#调用C++ DLL为例,深入剖析了从DLL导出、P/Invoke调用到复杂数据类

weixin_30703911的博客 296

C#调用C/C++动态库 封送结构体,结构体数组

   因为公司一直都是做C++开发的,因客户需要要提供C#版本接口,研究了一下C#,发现其强大简洁, 在跨语言调用方面封装的很彻底,提供了强大的API与之交互.这点比JNA方便多了. Java与C#都只能调用C格式导出动态库,因为C数据类型比较单一,容易映射. 两者都是在本地端提供一套与之映射的C#/java描述接口,通过底层处理这种映射关系达到调用的目的.     一. 结构体的传递   ...

weixin_34015860的博客 126

C++与C#跨语言互调实战:从PInvoke到C++/CLI的完整解决方案

在软件工程实践中,跨语言互操作是整合不同技术栈、复用遗留代码或发挥特定语言性能优势的关键技术。其核心原理在于定义清晰的二进制接口,并通过数据封送(Marshaling)在不同运行时环境间安全地传递数据和控制流。这项技术的价值在于能够将C++的高性能计算能力与C#的快速开发迭代优势相结合,广泛应用于图像处理、科学计算、游戏引擎插件以及工业控制等场景。本文聚焦于C++与C#的互操作,深入探讨了两种主流方案:通过PInvoke直接调用C风格DLL函数,以及利用C++/CLI构建面向对象的托管适配层。文章不仅解析了

weixin_30402231的博客 322

C# 与C++的数据转换

在集成工作中,经常会有用c#代码调用c++的dll,这里难免会有类型转化。在调用中经常出现的问题有; 1、结构体的重定义。 在c++中会有很多结构体,结构体内有各种各样的数据类型,所以就牵涉到数据类型的转化,同时在通过结构体获取到数据后,也牵涉到编码转化问题。 下面重点罗列下常用的类型转化。

图像处理的专栏 4233

C#调用C/C++动态库 封装结构体,结构体数组

一、结构体传递 #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数 typedef struct { int osVersion; int majorVersion; int minorVersion; int buildNum; ...

AI知识搬运工 3721
下一篇: GIS坐标系与地图投影
修哥
博客等级 码龄14年 71粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值