• C++调用C#的动态库dll


      以往我们经常是需要使用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组件这种做法已经很古老,而且相当繁琐,所以不是迫不得已,一般不会采用这种方式。

      

  • 相关阅读:
    jdbc批量插入后返回批量id
    java 实现逻辑表达式解析
    jdbctemplate 批量插入 返回自增id
    谷歌浏览器 jsonVue 插件
    两个检查有无数据的sql语句
    Java
    Webview学习笔记 Hello
    调度器35—相关DEBUG汇总 Hello
    设计模式总结汇总 Hello
    kernel syscore 学习笔记 Hello
  • 原文地址:https://www.cnblogs.com/zhuweisky/p/16347113.html
Copyright © 2020-2023  润新知