以往我们经常是需要使用C#来调用C++的dll,这通过PInvoke就能实现。现在在实际的项目过程中,有时会遇到在C++的项目中调用某个C#的dll来完成特定的某个功能,我们都知道,Native C++是没办法直接调用.NET平台的dll的。那有没有办法来做到这一点了?答案是肯定的。

  我们以OMCS实时音视频框架为例,OMCS WinPC 版的SDK是C#开发的,有些使用C++ QT开发Windows应用的客户,想调用OMCS来进行语音视频会话或远程桌面等功能,那该怎么做了?

一.基本原理

  虽然,Native C++是调用不了C#的dll的,但是Managed C++(C++/CLI)可以调用C#的dll,所以,可以使用C++/CLI作为桥梁来将 Native C++ 和 C#连接起来。

(1)新建一个C++/CLI的库(比如名称为OmcsWrap),添加引用并调用OMCS.dll,使用Managed C++语法调用OMCS.dll中的组件,并暴露出标准的C/C++接口。

(2)编译C++/CLI库得到 OmcsWrap.dll 和 OmcsWrap.lib。该库的接口是符合C++规范的。

(3)在Native C++项目(如QT)中,链接 OmcsWrap.dll、OmcsWrap.lib即可。

二.C++/CLI调用C#版的OMCS示例

  如果了解OMCS的基本用法(不了解的可以查看:OMCS入门Demo:语音视频、电子白板、远程桌面 功能展现),那么下面的C++/CLI的调用代码就很容易理解了。

  我们新建一个C++/CLI的控制台项目,来演示如何通过OMCS的摄像头连接器连接到任意一个在线用户的摄像头,拿到摄像头的视频图像Bitmap数据。

using namespace System;
using namespace System::Drawing;
using namespace OMCS::Passive;
using namespace OMCS::Passive::Video; ref class Tester
{
private:
DynamicCameraConnector^ dynamicCameraConnector;
int frameCount = 0; public: Tester()
{
IMultimediaManager^ mgr = MultimediaManagerFactory::GetSingleton(); //登陆 aa09
mgr->Initialize("aa09", "", "127.0.0.1", 9900);
Console::WriteLine(L"登录OMCS服务器成功!");
} void Start()
{
dynamicCameraConnector = gcnew DynamicCameraConnector();
dynamicCameraConnector->NewFrameReceived += gcnew ESBasic::CbGeneric<array<unsigned char, 1>^>(this, &Tester::OnNewFrameReceived);
dynamicCameraConnector->ConnectEnded += gcnew ESBasic::CbGeneric<OMCS::Passive::ConnectResult>(this, &Tester::OnConnectEnded); //连接自己的摄像头
dynamicCameraConnector->BeginConnect(L"aa09");
} //摄像头图像数据
void OnNewFrameReceived(array<unsigned char, 1>^ rgb24)
{
Bitmap^ bm = ESBasic::Helpers::ImageHelper::ConstructRGB24Bitmap(rgb24, dynamicCameraConnector->VideoSize.Width, dynamicCameraConnector->VideoSize.Height); ++this->frameCount;
Console::WriteLine(L"收到图像帧:" + this->frameCount.ToString("00000"));
} //连接摄像头的结果
void OnConnectEnded(OMCS::Passive::ConnectResult result)
{
if (result == ConnectResult::Succeed) //连接成功
{
Console::WriteLine(L"连接摄像头成功!");
}
else
{
Console::WriteLine(L"连接摄像头失败!原因:" + result.ToString());
}
} void Stop()
{
if (this->dynamicCameraConnector != nullptr)
{
if (this->dynamicCameraConnector->Connected)
{
this->dynamicCameraConnector->Disconnect(); //断开到目标摄像头的连接
Console::WriteLine(L"断开摄像头连接器!");
} this->dynamicCameraConnector = nullptr;
}
}
};

(1)这里仅仅是将收到的摄像头视频图像帧的帧数打印出来,真实的使用场景中,可以将图像帧回调传给QT,QT就可以在UI控件上将图像渲染出来。这样就可以看到视频了。

(2)这里是以摄像头为例,桌面也是完全一样的模式,使用DynamicDesktopConnector。

(3)对于麦克风声音,则更简单一下,因为其不需要UI渲染,所以直接在C++/CLI中调用MicrophoneConnector就可以了。连接目标麦克风成功,本地电脑就会自动播放其声音。

启动OMCS服务端(可从文末下载)后,运行本文的控制台程序,运行效果如下截图所示:

  这里只是简单的示意一下C++/CLI调用OMCS的方式,至于封装一个给Native C++来调用C++/CLI库,这个库要提供哪些API,则取决于具体的项目需求,这里就不举例了。

三. Demo 源码下载

1. C++/CLI调用OMCS Demo:CppCli-CallOMCS-Demo.rar

2. Demo 服务端+C#客户端:OMCS.Demos.Simplest.rar

  关于OMCS实时视频功能的demo介绍,请参见这里

  最后提一下,还有一种 Native C++ 调用C#的dll的方式,是使用COM组件。

  这种方式是在C#的dll外再封装一层,将其接口全部转换成COM接口,如此,标准的COM组件就可以被Native C++调用了。

  COM组件这种做法已经很古老,而且相当繁琐,所以不是迫不得已,一般不会采用这种方式。

  

C++调用C#的动态库dll的更多相关文章

  1. C#直接使用DllImport调用C/C++动态库(dll文件)

    1.C/C++动态库的编写 下面是我编写的一个比较简单的C++dll文件用来测试,关于如何编写dll文件,我这里便不再赘述,不懂得自行查询, (1).h文件 #ifdef MYDLL_EXPORTS ...

  2. 在VS2015中用C++编写可被其它语言调用的动态库DLL

    转自:http://blog.csdn.net/songyi160/article/details/50754705 VS2015用C++创建动态库DLL步骤如下: (1)启动VS2015>文件 ...

  3. C++与C#有关对库(动态库dll,静态库.lib)文件的调用

    1 动态库的相互调用 1.1 C#调用C++ dll步骤(只能导出方法): 1. c++建立空项目->源文件文件夹中添加cpp文件和函数 2. c++属性设置中,配置类型设置为动态库dll,公共 ...

  4. Qt生成和调用动态库dll,和静态库.a(windows和linux通用)

    系统1:ThinkPad T570.Windows10.QT5.12.2(Qt Creater 4.8.2)一.动态库.dll的创建和调用1.在qtcreater中按如下步骤创建动态库,动态库名为my ...

  5. 关于C#调用非托管动态库方式的性能疑问

    最近的项目中,因为一些原因,需要C#调用非托管(这里为C++)的动态库.网上喜闻乐见的方式是采用静态(DllImport)方式进行调用.偶然在园子里看到可以用动态(LoadLibrary,GetPro ...

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

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

  7. C# 调用其他的动态库开发应注意的问题

    1.背景 程序开发语言可以说是五花八门,这就引出了一个新问题 ,不同语言开发的系统进行对接时相关调用的问题. 下面我主要说一下我自己在做接口开发时遇到的问题及解决方法仅供参考,我使用的C#开发进行对接 ...

  8. 五,动态库(dll)的封装与使用

    在项目开发中,我们经常会使用到动态库(dll),要么是使用别人的动态库,要么是将功能函数封装为动态库给别人用.那么如何封装和使用动态库呢?以下内容为你讲解. 1.动态库的封装 以vs2010为例,我们 ...

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

    C#调用C/C++动态库,封装各种复杂结构体. 标签: c++结构内存typedefc# 2014-07-05 12:10 6571人阅读 评论(1) 收藏 举报  分类: C(8)  C#(6)  ...

随机推荐

  1. Windows中Nginx配置nginx.conf不生效解决方法(路径映射)

    Windows中Nginx配置nginx.conf不生效解决方法 今天在做Nginx项目的时候,要处理一个路径映射问题, location /evaluate/ { proxy_pass http:/ ...

  2. Android搞定权限申请

    0x00 前言 使用EasyPermissions库进行申请权限 打开App时就申请权限,如果用户拒绝权限后,会循环申请 如果永久拒绝后,会跳转到设置里继续申请 效果图: 注:不讲原理,先教你怎么实现 ...

  3. Windows和ubuntu下更改pip国内镜像

    windows下更改pip国内镜像 # 在C:\Users\admin路径下创建pip文件夹,然后创建pip.ini文件, 并在文件下写入 [global] index-url = http://py ...

  4. spring-注入集合对象

    1.创建Stu类 package com.spring.collections; import java.util.Arrays; import java.util.List; import java ...

  5. 那些年uniapp踩过的坑之-------搜索框插件uni-search-bar字体和图标居中的问题

    用uniapp必不可少的就是搜索框 但是公司要求的是这样滴 但是 uni-search-bar这个插件给我的偏偏是这样子滴 这个时候我以为是简简单单的样式问题,但是多方调试无果之后才发现,这两个根本不 ...

  6. vue - 文字3d展示

    <template>   <div>     <p>     <span>C</span>     <span>S</sp ...

  7. Anaconda下安装Tensorflow、keras问题及解决办法

    这两天一直在跟tensorflow的错误日志作斗争!安装过程中出现各种问题,找资料,采坑,终于装好了,做个小总结! keras需要在TensorFlow之上才能运行,所以需要先安装TensorFlow ...

  8. PHP入门-Window 下利用Nginx+PHP 搭建环境

    前言 最近公司有个PHP项目需要开发维护,之前一直都是跟着巨硬混的,现在要接触PHP项目.学习一门新语言之前,先搭建好环境吧,鉴于公司项目是基于php 7.1.33 版本的,所以以下我使用的都是基于这 ...

  9. 5. VIM编辑器

    Vim编辑器中设置了3种模式-命令模式.末行模式和编辑模式 命令模式:控制光标移动,可对文本进行复制.粘贴.删除和查找等工作. 输入模式:正常的文本录入. 末行模式:保存或退出文档,以及设置编辑环境. ...

  10. Linux根目录下各文件目录的作用

    bin        用户二进制可执行文件    boot        系统启动引导文件    dev[device]        系统中使用的外部设备,但不是放的外部设备的驱动.一个访问这些外部 ...