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組件這種做法已經很古老,而且相當繁瑣,所以不是迫不得已,一般不會採用這種方式。

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章