为了跨平台在.net core中使用COM,不能使用Windows下的COM注册机制,但是可以直接把IUnknown指针传给C#,转换为指针,再转换为C#的接口(interface)。

做了这方面的研究,但最终我没有使用这套技术,因为对IDispatch::Invoke的分发太麻烦了,又不能借助ATL与VS开发环境的IDL能力。所以没有继续研究事件订阅(C#是event,C++COM是IConnectionPoint)。

C++中需要做的:

简单点,实现IDispatch就可以了,全面一点,实现IManagedObject或IProvideClassInfo,后者可是个大工程。

如果我们要实现C#中定义的接口,那么最好给(不给也可以,编译器会给每个接口一个默认的GUID)接口一个GUID,.net到你的对象QueryInterface时要处理这个IID,把IDispatch指针与S_OK返回即可。

如果跨平台,把__uuidof换成实际的UUID即可。

struct foo : public IDispatch
{
// 通过 IDispatch 继承
virtual ULONG AddRef(void) override{return 0;}
virtual ULONG Release(void) override{return 0;}
virtual HRESULT QueryInterface(REFIID riid, void ** ppvObject) override
  {
if (riid == __uuidof(IUnknown))
{
*ppvObject = (IUnknown*)this;
return S_OK;
}
IID uid;
IIDFromString(L"{C#声明接口的GUID/IID}", &uid);
if (riid == uid)
{
*ppvObject = (IDispatch*)this;// (IUnknown*)this;
return S_OK;
}
if (riid == __uuidof(IDispatch))
{
*ppvObject = (IDispatch*)this;
return S_OK;
}
return E_NOTIMPL;
   } virtual HRESULT GetTypeInfoCount(UINT * pctinfo) override{return S_OK;}
virtual HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo ** ppTInfo) override{return S_OK;}
virtual HRESULT GetIDsOfNames(REFIID riid, LPOLESTR * rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId) override
{
*rgDispId = 1;
return S_OK;
} virtual HRESULT Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pDispParams, VARIANT * pVarResult, EXCEPINFO * pExcepInfo, UINT * puArgErr) override
{
cout << "be called" << endl;
return S_OK;
}
};

  

再导出一个DLL的函数把指针给.net运行时

extern "C" __declspec(dllexport)
foo* WINAPI GetTestObject()
{
return new foo;// 简单粗暴leak :)
}

C#代码:

[DllImport(@"foo.dll")]
static extern IntPtr GetTestObject(); [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("your uiid")]
interface Test
{
int func();
} var v = GetTestObject();
obj = (Test)Marshal.GetObjectForIUnknown(v);
var value = obj.func();// 输出be called

I love COM

COM思想很重要,COM最近不但活跃在Windows平台,更是蔓延到了Linux,安卓,iOS等平台。架构师,程序员应合理利用。

C#调用原生C++ COM对象(在C++中实现C#的接口)的更多相关文章

  1. OC 继承子类对象调用方法机制 子类对象访问父类中的实例变量

    在继承中,子类对象如何调用到正确方法的机制 每一个Objective - C对象都有一个隐藏的指针指向类的代码,当向一个对象发送消息的时候,当前的对象会首先在当前类里去查找相应的方法,如果找到的话,直 ...

  2. Dcloud HTML5 监听蓝牙设备 调用 原生安卓实现

    最近一直搞Dcloud ,这是HTML5版本的开发,打包时候,可以打包成 apk 和ipa 分别运行在安卓和ios 机器上面, 但是这里面的资料很少,遇到问题,之后只能自己钻研总结, 现在有这么一个需 ...

  3. iOS开发--JS调用原生OC篇

    JS调用原生OC篇 方式一(反正我不用) 第一种方式是用JS发起一个假的URL请求,然后利用UIWebView的代理方法拦截这次请求,然后再做相应的处理. 我写了一个简单的HTML网页和一个btn点击 ...

  4. ionic-native-transitions调用原生页面切换实现ionic路由切换

    废话不多说:ionic-native-transitions调用原生页面切换实现ionic路由切换,从而大大提升ionic应用的性能. ionic-native-transitions是一个ionic ...

  5. PHP“Cannot use object of type stdClass as array” (php在调用json_decode从字符串对象生成json对象时的报错)

    php再调用json_decode从字符串对象生成json对象时,如果使用[]操作符取数据,会得到下面的错误 错误:Cannot use object of type stdClass as arra ...

  6. BeanFactory调用getbean()对象

    Spring通过资源加载器加载相应的XML文件,使用读取器读取资源加载器中的文件到读取器中,在读取过程中,解析相应的xml文件元素,转化为spring定义的数据结BeanDefinition,把相应的 ...

  7. Ext JS学习第九天 Ext基础之 扩展原生的javascript对象

    此文来记录学习笔记: •Ext对于原生的javascript对象进行了一系列的扩展,我们把他们掌握好,更能深刻的体会Ext的架构,从而对我们的web开发更好的服务, 源码位置,我们可以从开发包的这个位 ...

  8. Ext JS学习第十天 Ext基础之 扩展原生的javascript对象(二)

    此文来记录学习笔记: 今天继续说Ext.Array,Ext.Function,Ext.Date,Ext.Error ------------------------------------------ ...

  9. C++ Primer 学习笔记_62_重载操作符与转换 --调用操作符和函数对象

    重载操作符与转换 --调用操作符和函数对象 引言: 能够为类类型的对象重载函数调用操作符:一般为表示操作的类重载调用操作符! struct absInt { int operator() (int v ...

随机推荐

  1. nginx介绍(二) 架构篇

    2. nginx架构总览 传统的基于进程或者基于线程的模型处理并发的方式都是为每个连接单独创建一个处理进程或线程,会在网络传输或者I/O操作上阻塞.而这对应用来说,在内存和 CPU的使用上效率都是非常 ...

  2. Kubernetes 持续集成 SpringCloud

    写在开始之前,在开始之前我们需要了解几个概念: 1.什么是持续集成? 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成.每次 ...

  3. 搞懂ES6的import export

    引言 说来惭愧,这两个关键字几乎天天在写,但是自己写的模块export出去的对象,import居然拿不到,也是没谁了

  4. shiro 返回json字符串 + 自定义filter

    前言: 在前后端分离的项目中, 在使用shiro的时候, 我们绝大部分时候, 并不想让浏览器跳转到那个页面去, 而是告诉前端, 你没有登录, 或者没有访问权限. 那这时候, 我们就需要返回json字符 ...

  5. 03 使用Tensorflow做计算题

    我们使用Tensorflow,计算((a+b)*c)^2/a,然后求平方根.看代码: import tensorflow as tf # 输入储存容器 a = tf.placeholder(tf.fl ...

  6. win32程序之窗口程序,以及消息机制

    win32程序值窗口程序,以及消息机制 一丶简介 通过上一讲.我们了解了窗口其实是绘制出来的.而且是不断绘制的过程. 所以窗口的本质是绘制. 但是我们现在看到的窗口程序.都可以点击关闭按钮. 使用鼠标 ...

  7. MySQL 高性能优化实战总结

    1 前言 2 优化的哲学 3 优化思路 3.1 优化什么 3.2 优化的范围有哪些 3.3 优化维度 4 优化工具有啥? 4.1 数据库层面 4.2 数据库层面问题解决思路 4.3 系统层面 4.4 ...

  8. Perl模块管理

    Perl模块管理 perl有自带的模块,还有第三方模块.自带的模块是随perl安装而安装好的,第三方模块需要从CPAN(Comprehensive Perl Archive Network)上下载并安 ...

  9. Go基础系列:空接口

    空接口 空接口是指没有定义任何接口方法的接口.没有定义任何接口方法,意味着Go中的任意对象都可以实现空接口(因为没方法需要实现),任意对象都可以保存到空接口实例变量中. 空接口的定义方式: type ...

  10. 部署vmware-vcsa 6.5

    介绍一下vcsa vsphere的两个最重要的组件是esxi和vcenter server,esxi是虚拟化主机管理软件,而vcenter server则是管理.组织多台esxi主机的管理中心. es ...