C#调C++库:回调、结构体(结构体嵌套结构体数组)传入数据、结构体传出数据的例子

#创造灵感#

:工作实践,最近实现了一个c++的消息总线类库,第三方使用C#需要调用,故做了一个demo程序

关于回调

c#使用delegate 定义回调签名。

传入结构体

c++定义的参数类型是结构体指针且结构体内部包含结构体动态数组指针,在定义C#结构体时外层结构体里面要用IntPtr代替内层结构体数组

传出结构体

此C++类库的设计是外部调用开辟内存空间,内部进行字符串和数字的填充。所以创建对应的C#结构体对象时字符串字段需要开辟足够的空间并以0填充

Don't BB,Show me Code!!!(c++头文件后续再发)

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

namespace MlinebusTest
{
    public struct MBTopicExtern {
       public string name;//主题名
        public int rspModel;//消息应答类型,
        public string version;//版本号,可以不填
    }
    public struct ConnectOptExtern {
        public string host;//服务器地址
        public int port;//服务器端口
        public  string groupName;//所在流水线组名,同一条流水线有相同的组名
        public string userName;//用户名,
        public string password;//密码
        public  string id; //用户唯一标识,全局唯一
        public  int role;//0-普通客户端,1-中控,需要知道其它节点是否上、下线
        public  IntPtr topics; //订阅主题数组
        public int topicsSize;//主题长度

        public int minRetryInterval;//最小间隔时间,
        public int maxRetryInterval;//最大间隔时间,最小和最大间隔其中有一个为0将采用默认间隔时间1s和30s
    }

    public struct MsgExt {
        public string groupName;//发送者组名
        public string sender;//发送者id
        public string version;//版本好
        public string payload;//消息内容
        public int payloadlen;//消息长度
    }

    //[StructLayout(LayoutKind.Sequential)]
    public struct MsgRsp {
     //   [MarshalAs(UnmanagedType.ByValTStr,SizeConst =100)]
        public string groupName;//发送者组名
       // [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]

        public string sender;//发送者id
      //  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]

        public string version;//版本好
       // [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2048)]
        public string payload;//消息内容
        public int payloadlen;//消息长度
};

    public struct  MBAddress {
	string groupName;//用户所在组名
        string userId;//用户id
};

public delegate void ReceiveMsgCBDelegate(string topic, int size, MsgExt ext);
    public delegate void ConnectLostCBDelegate(string host , int port);
    public delegate void TrackLogCBDelegate(string  msg);
    public delegate void UserOnlineChangedCBDelegate(string groupName,string userName , bool isOnline);
    class Program
    {
        [DllImport("mlinebus.dll", EntryPoint = "mb_MBErrToStr")]
       static extern IntPtr mb_MBErrToStr(int code);

        [DllImport("mlinebus.dll",EntryPoint = "mb_connnect")]
        static extern int mb_connnect(ConnectOptExtern option);

        [DllImport("mlinebus.dll", EntryPoint = "mb_setCallback")]
        static extern int mb_setCallback(ConnectLostCBDelegate ctlostcb, TrackLogCBDelegate logcb, ReceiveMsgCBDelegate receiveMsgcb, UserOnlineChangedCBDelegate userChangedcb);
        [DllImport("mlinebus.dll", EntryPoint = "mb_request")]
        static extern int mb_request(string topic, string payload, ref MsgRsp response, int timeout, string version, IntPtr address);

        static void Main(string[] args)
        {


            Console.WriteLine("123");

          IntPtr errmsg=  mb_MBErrToStr(1);
           
            string err = Marshal.PtrToStringAnsi(errmsg);
            Console.WriteLine(err);



            ConnectLostCBDelegate ctlostcb= ConnectLostCBHandler;
            TrackLogCBDelegate logcb= TrackLogCBHandler;
            ReceiveMsgCBDelegate receiveMsgcb = ReceiveMsgCBHandler;
            UserOnlineChangedCBDelegate userChangedcb= UserOnlineChangedCBHandler;
            int code=mb_setCallback(ctlostcb, logcb, receiveMsgcb, userChangedcb);
            if (code == 0)
            {
                Console.WriteLine("mb_setCallback success");
            }
            else {
                Console.WriteLine("mb_setCallback failed");
                Console.ReadKey();
                return;
            }
            ConnectOptExtern opt=new ConnectOptExtern();
            opt.host = "127.0.0.1";
            opt.port = 1883;
            opt.groupName = "testline";
            opt.userName = "6001";
            opt.password = "maccura";
            opt.id = "6001_1";

           // opt.topics = new MBTopicExtern[2];
            
            int topicCount = 3;
            opt.topicsSize = topicCount;

            int topicSize = Marshal.SizeOf<MBTopicExtern>();
            Console.WriteLine("size of MBTopicExtern="+ topicSize);

            IntPtr pBuff = Marshal.AllocHGlobal(topicSize * topicCount);
            long ptrHead = pBuff.ToInt64();
            MBTopicExtern[] topic = new MBTopicExtern[topicCount];

            topic[0].name = "firstTopic";
            topic[0].rspModel = 0;
            topic[0].version = "";
            IntPtr firstPtr = new IntPtr(ptrHead);
            Marshal.StructureToPtr(topic[0], firstPtr, false);

            topic[1].name = "secondTopic";
            topic[1].rspModel = 0;
            topic[1].version = "";
            IntPtr secondPtr = new IntPtr(ptrHead+ topicSize);
            Marshal.StructureToPtr(topic[1], secondPtr, false);


            topic[2].name = "orderinfo";
            topic[2].rspModel = 1;//request
            topic[2].version = "";
            IntPtr thirdPtr = new IntPtr(ptrHead + topicSize*2);
            Marshal.StructureToPtr(topic[2], thirdPtr, false);

            opt.topics = pBuff;

            int ret = mb_connnect(opt);

            //release memory
            Marshal.FreeHGlobal(pBuff);


            //demo how to request
            MsgRsp rsp = new MsgRsp();
            rsp.groupName = new String(new char[100]);
            rsp.sender = new String(new char[100]);
            rsp.version = new String(new char[100]);
            char[] a = new char[10000];
            rsp.payload = new String(new char[100]);
            rsp.payloadlen = 10000;
            int rspSize = Marshal.SizeOf<MsgRsp>();

            //    IntPtr rspPtr = Marshal.AllocHGlobal(rspSize);

            // Marshal.StructureToPtr(rsp, rspPtr, false);


            code = mb_request("orderinfo", "{name:123}", ref rsp, 5, "", IntPtr.Zero);
            if (code != 0)
            {
                Console.WriteLine("request failed,code= " + code);
            }
            else
            {

                // var  result= Marshal.PtrToStructure<MsgRsp>(rspPtr);

                Console.WriteLine("request success:");
                Console.WriteLine("response groupName= " + rsp.groupName);
                Console.WriteLine("response sender= " + rsp.sender);
                Console.WriteLine("response version= " + rsp.version);
                Console.WriteLine("response payloadlen= " + rsp.payloadlen);
                Console.WriteLine("response payload= " + rsp.payload.ToString());

            }


            while (Console.ReadKey().KeyChar != 'a') { };
        }

        public static void ReceiveMsgCBHandler(string topic, int size, MsgExt ext) {

            Console.WriteLine("ReceiveMsgCBHandler called:");
            Console.WriteLine("    topic= " + topic);
            Console.WriteLine("    size= " + size);
            Console.WriteLine("    payloadlen= " + ext.payloadlen);
            Console.WriteLine("    payload= " + ext.payload);
        }
        public static void ConnectLostCBHandler(string host, int port) {
            Console.WriteLine("ConnectLostCBHandler called: host="+host+" ,port="+port);

        }
        public static void TrackLogCBHandler(string msg) {
            Console.WriteLine("TrackLogCBHandler called");
            Console.WriteLine("TrackLogCBHandler called: "+ msg);
        }
        public static void UserOnlineChangedCBHandler(string groupName, string userName, bool isOnline) {
            Console.WriteLine("UserOnlineChangedCBHandler called");

        }
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值