C++調用C#的動態庫dll
- 2022 年 6 月 6 日
- 筆記
- 02. 語音影片技術與實現
以往我們經常是需要使用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組件這種做法已經很古老,而且相當繁瑣,所以不是迫不得已,一般不會採用這種方式。