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

对于一些比较复杂的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*。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值