这种方式比较简单,给大家分享一下,同时讲一下SafeArray内定义结构体的方法

1. 需求描述

需求是这样的,C++代码和C#代码相互通信(C++一般做服务,C#做客户端),C++一侧准备好数据,然后发给C#端解析,这种需求还是比较常见的。

但是由于数据比较复杂,是一个数据结构,还可能数据结构里套用数据结构,总之数据很复杂(其实我觉得使用xml字符串传递比较理想,兼容性也比较好,但作为程序员有时候没有选择的权利)

2. 定义COM文件,idl文件

对于这个文件不熟悉的自己百度谷歌查查吧。

首先在文件里定义回调接口,也就是C#端需要继承的接口

[object, uuid, oleautomation,helpstring,...] // 内容自己填吧

interface IDataEvent : IUnknown{

  HRESULT OnDataEvent([in] SAFEARRAY(struct SData)* psaDataList);

};

其次定义C++导出接口,也就是C++端需要继承的接口

[object, uuid, dual, nonextensible,...]

interface IDataServer : IDispatch{

  ......

  [id(n)] InitCallback([in] IDataEvent* pCallback);  // 你也可以改为AddListener什么的

};

然后需要定义你的结构体和相关的其他信息

[uuid...]

library DataServer{

  enum EnumType{

    XXX_YYY = 0x01,......

  };

  [uuid...]

  struct SData{

    BSTR name;

    LONGLONG time;  // 使用longlong表示filetime,这个里边不仅有年月日十分秒,还有毫秒信息,更重要的是UTC时间

    VARIANT saValueList;  // 在C#端变成object,根据具体的类型再强转吧,或者在C#端一直保持object类型的状态,你也可以直接使用double或BSTR等类型

    SAFEARAY(xxxx) saList;  // 定义你自己的类型,别忘了xxxx需要定义好哦!

  };

  ......

};

这个文件编译时会生成tlb文件,交给C#直接添加reference就可以啦,如果添加失败,可以手动转换,使用.NET提供的编译工具“Tlbimp”,命令行参考如下

tlbimp myLib.tlb /out:myLib.dll

也可以直接在代码里import这个tlb文件,只不过使用tlb里导出的类型有点不太方便。

3. C#端处理

一般的处理过程是这样的

(1)启动部分,通过各自的手段获得C++端提供的服务对象,将其强转成导出接口对象IDataServer

(2)自己创建一个类用于接受数据 class DataClient : IDataEvent,调用IDataServer的注册回调的函数,将DataClient对象传给C++端

(3)在DataClient类中实现这个函数 public void OnDataEvent(ref Array psaDataList),解析数据吧,遍历Array,将内容强转成SData

这里需要注意的是,一般服务端返回数据时,由于数据量可能比较大,都是通过一个子线程完成的,所以C#端的这个OnDataEvent函数需要判断当前是否是UI线程,如果不是的话,不要直接改变UI,这可能导致UI锁住,正确的做法使用异步处理方式,比如将数据缓存起来,等待UI处理,或者使用UI.InvokeRequired方法与UI抢控制权,然后再处理UI。

4. C++端处理数据

C++端填充数据的过程是这样的

CComPtr<IRecordInfo> pRecord;
GetRecordInfoFromGuids(LIBID_xxx, 1, 0, ::GetUserDefaultLCID(), __uuid(SData), &pRecord);
......
SAFEARAY *psa = ::SafeArrayCreateEx(VT_RECORD, 1, &bound, pRecord);
::SafeArrayAccessData(psa, (void**)&pList);
...... // fill data
::SafeArrayUnaccessData(psa);

CSharpObj->OnDataEvent(&psa); // send to C# object

::SafeArrayAccessData(psa, (void**)&pList);
...... // release data
::SafeArrayUnaccessData(psa);
::SafeArrayDestory(psa);

浅尝辄止——在C++中调用C#的回调函数——COM方式的更多相关文章

  1. Unity C# 调用 C++ DLL 并在 DLL 中调用 C# 的回调函数

    Unity C# 调用 C++ DLL 并在 DLL 中调用 C# 的回调函数~~~    呵呵... 看着有点晕.. 再解释一下就是 在Unity中 使用 C# 调用 C++ 写的 DLL, 但是在 ...

  2. python中进程池和回调函数

    一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...

  3. Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程

    Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...

  4. unity 在脚本B中调用脚本A的函数

    一,在脚本B中调用脚本A的函数. 脚本A: //myFuncs.cs using UnityEngine;using System.Collections; namespace myFuncs{    ...

  5. C++ 使用回调函数的方式 和 作用。 持续更新

    先看两个demo: 一.在类test1中调用函数print() ,把print()的函数指针传递给test1的函数指针参数 test1.h: #include <stdio.h> #inc ...

  6. 关于as中的事件与回调函数

    对于Observer模式, 在as中object(被观察者)既可以用事件(event),也可以用回调函数(caller)来通知观察者(observer).那在实际的开发中到底应该选择用event还是用 ...

  7. PHP – 在类中使用array_filter时回调函数的问题

    了一个类处理好友,其中有一个方法用来同步好友,而这个方法中需要从微博传来的关注列表和粉丝列表中,找到互相关注的用户,记录一下经验,主要还是关于回调函数. 按照我最初的理解,这样写就可以了 privat ...

  8. 基于Lwip协议栈中独立模式下回调函数的使用

    一.使用Lwip协议独立模式开发 最近在STM32F4上边移植了Lwip,Lwip是一个小型开源的TCP/IP协议栈,有无操作系统的支持都可以运行.我当前只测试了TCP Server功能,然后对TCP ...

  9. JS与OC交互,JS中调用OC方法(获取JSContext的方式)

    最近用到JS和OC原生方法调用的问题,查了许多资料都语焉不详,自己记录一下吧,如果有误欢迎联系我指出. JS中调用OC方法有三种方式: 1.通过获取JSContext的方式直接调用OC方法 2.通过继 ...

随机推荐

  1. FPGA书籍

    Xilinx FPGA开发实用教程(第2版) 徐文波,田耘 著

  2. java标准-密码用数组比用字符串安全

    转载:http://my.oschina.net/jasonultimate/blog/166968 1) Since Strings are immutable in Java if you sto ...

  3. 终极解决maya渲染层丢材质,变线框等问题

    终极解决maya渲染层丢材质,变线框等问题 相信有很多同志在使用maya做灯光渲染的时候,经常能遇到渲染层的模型丢材质.变线框等问题,特别恶心.我也经常遇到,所以和大家分享一下我的解决或尽量避免的方法 ...

  4. 依赖注入 – ASP.NET MVC 4 系列

           从 ASP.NET MVC 3.0 开始就引入了一个新概念:依赖解析器(dependence resolver).极大的增强了应用程序参与依赖注入的能力,更好的在 MVC 使用的服务和创 ...

  5. 用CorelDRAW等分分割图片的方法

    在CorelDRAW中,想要将图片等分分割可以通过放置容器来实现,根本不需要裁剪工具和辅助线.例如两等分:首先要建立确定等分的份数,建立长方形或正方形.然后把图片放置容器,调整位置,做无缝拼接就可以了 ...

  6. Chrome Devtools简介

    Chrome开发工具(又称DevTools),是一套内嵌在chrome浏览器内部的web编写和调试工具.DevTools提供给web开发人员深入地访问浏览器内部和web应用的机会.DevTools可以 ...

  7. 第一章 数据库概述、MySQL的安装和配置

      第一章 数据库概述.MySQL的安装和配置   1.为什么要使用数据库 最早是纸质文件来存储数据 缺点:不易保存,占用空间大 计算机出现以后,采用软件来进行保存(excel) 缺点:容易损坏 文件 ...

  8. 将 ASP.NET MVC3 Razor 项目部署到虚拟主机中

    国内很多网站空间都只支持.NET 2.0 和 .NET 3.0 3.5,很少有空间商支持.NET 4的,即使有个别支持.NET 4,但是不支持MVC的默认路由访问形式. Go Daddy 的主机支持, ...

  9. IntentService

    http://developer.android.com/training/run-background-service/index.html IntentService 只是简单的对Service做 ...

  10. fdisk -c 0 350 1000 300命令

    在Linux中有一个fdisk的分区命令,在对开发板的nand或者emmc分区也会用到这个命令, fdisk -c 这里0 350 1000 300分别代表: 每个扇区大小为0,一共350个柱面,起始 ...