前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c#开发的客户端,如何调用c++开发的sdk dll库

c#开发的客户端,如何调用c++开发的sdk dll库

原创
作者头像
Tomas7571
修改2021-05-18 10:36:04
5.1K0
修改2021-05-18 10:36:04
举报
文章被收录于专栏:Tomas7571的专栏Tomas7571的专栏

一、整体思路

c#客户端不能直接调用c++ dll,需要做2个黏合层把它们连接起来,这里以trtc sdk的dll为例

二、实现步骤

1.  先写个从c#客户端调用c++ dll完成trtc初始化的功能

(1) 创建一个c#客户端(选择windowsform)项目
(2) 在程序入口main()函数中,加入InitWrapper()准备用来初始化trtc sdk

Program.cs

代码语言:txt
复制
//初始化TRTC SDK 
//调用链路:WindowsFormsApp1.exe(c#) -> RTCManager.dll(c#) -> TRTCWrapper.dll(c++) -> liteav.dll(c++,要调用的目标dll)
int nRet = RTCWrapper.InitWrapper();

(3) 创建RTCManager.dll(选择.netframework库)c# 项目
(4) 创建RTCWrapper c#类,并用DllImport映射c++ dll中的接口InitWrapper()

TRTCWrapper.cs

代码语言:txt
复制
public static class RTCWrapper
{
        /// <summary>
        /// 初始化TRTC
        /// </summary>
        /// <returns>1成功,0失败</returns>
        [DllImport("TRTCWrapper.dll", EntryPoint = "InitWrapper")]
        public static extern int InitWrapper();
}

(5) 创建TRTCWrapper.dll(选择动态链接库) c++项目
(6) 实现InitWrapper接口

TRTCWrapper.h

代码语言:txt
复制
//初始化TRTC
extern "C" __declspec(dllexport) int _stdcall InitWrapper();

TRTCWrapper.cpp

代码语言:txt
复制
_declspec(dllexport) int _stdcall InitWrapper()
{
    trtcInstance = TRTCCloudCore::GetInstance();
 
    if (trtcInstance)
    {
        trtcInstance->Init();
        return 1;
    }
    else
        return 0;
}

(7) 在GetInstance()中加载trtc sdk的dll库,注意这里要用动态加载dll的方式,不然编译不过。Init()有其他作用,可以用来设置回调

TRTCCloudCore.cpp

代码语言:txt
复制
TRTCCloudCore* TRTCCloudCore::GetInstance()
{
    if (m_instance == NULL) {
        engine_mex.lock();
        if (m_instance == NULL)
        {
            m_instance = new TRTCCloudCore();
        }
        engine_mex.unlock();
    }
    return m_instance;
}
 
TRTCCloudCore::TRTCCloudCore()
{
    trtc_module_ = nullptr;
    if (trtc_module_ != nullptr) return;
 
    HMODULE hmodule = NULL;
    GetModuleHandleEx(
        GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
        L"TRTCModule", &hmodule);
 
    char module_path[MAX_PATH] = { 0 };
    ::GetModuleFileNameA(hmodule, module_path, _countof(module_path));
 
    std::string module_dir = GetPathNoExt(module_path);
    if (module_dir.length() == 0) {
        LINFO(L"TRTC GetModule Path Error");
        return;
    }
 
    std::string module_full_path = module_dir + "liteav.dll";
 
    trtc_module_ =
        ::LoadLibraryExA(module_full_path.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}

注意:

1.设置项目之间的依赖关系

2.添加trtc对应的include,lib目录

3.设置dll的生成目录,跟c# exe在一起,这样方便调试,不用写脚本copy

2. 接着实现sdk的回调通知给主程序

(1) 在程序入口main()函数中,加入AddTRTCMsgCallBack()准备用来注册trtc的回调

Program.cs

代码语言:txt
复制
//注册SDK的callback
RTCDelegate rtcDelegate = new RTCDelegate();
RTCWrapper.AddTRTCMsgCallBack(rtcDelegate.rtcCallBack);

(2) 在RTCManager.dll中实现RTCDelegate c#类,用来接收trtc sdk的回调

RTCDelegate.cs

代码语言:txt
复制
enum TRTC_MSG
{
    TRTC_MSG_onEnterRoom = 1,
    TRTC_MSG_onExitRoom,
    TRTC_MSG_onRemoteUserEnterRoom,
    TRTC_MSG_onRemoteUserLeaveRoom,
    TRTC_MSG_onError,
    TRTC_MSG_onWarning
    //TODO 补齐TRTC的回调
};
 
namespace RTCManager
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void RTCWrapperCallback(int trtcModule, int errCode, [In, MarshalAs(UnmanagedType.LPStr)] string errMsg);
 
 
    public class RTCDelegate
    {
        public RTCWrapperCallback rtcCallBack = null;
 
        public RTCDelegate()
        {
            Setcallback();
        }
 
        private void RTCWrapperCallbackFun(int trtcModule, int errCode, [In, MarshalAs(UnmanagedType.LPStr)] string errMsg)
        {
            TRTC_MSG trtcMsg = (TRTC_MSG)trtcModule;
            switch (trtcMsg)
            {
                case TRTC_MSG.TRTC_MSG_onEnterRoom:
                    break;
                default:
                    break;
 
            }
        }
 
        public void Setcallback()
        {
            rtcCallBack = RTCWrapperCallbackFun;
        }
         
    }
}

(3) 用DllImport映射c++ dll中的接口AddTRTCMsgCallBack()

TRTCWrapper.cs

代码语言:txt
复制
/// <summary>
/// 注册TRTC通用回调
/// </summary>
/// <param name="callback">通用回调</param>
/// <returns></returns>
[DllImport("TRTCWrapper.dll", EntryPoint = "AddTRTCMsgCallBack")]
public static extern void AddTRTCMsgCallBack(RTCWrapperCallback callback);

(4) 在TRTCWrapper.dll中实现AddTRTCMsgCallBack()接口

TRTCWrapper.h

代码语言:txt
复制
//注册TRTC通用回调
extern "C" __declspec(dllexport) void _stdcall AddTRTCMsgCallBack(TRTCMsgCallback messageCallback);

TRTCWrapper.cpp

代码语言:txt
复制
_declspec(dllexport) void _stdcall AddTRTCMsgCallBack(TRTCMsgCallback messageCallback)
{
    if(trtcInstance)
        trtcInstance->MessageCallBack = messageCallback;
    //else 输出错误日志
}

(5) 把messageCallback设置到trtc sdk中

TRTCCloudCore.h

代码语言:txt
复制
typedef void(*TRTCMsgCallback)(int trtcModule, int errCode, const wchar_t* errMsg);
 
TRTCMsgCallback MessageCallBack = nullptr;

(6) 在trtc sdk的回调接口onEnterRoom中调用messageCallback

TRTCCloudCore.cpp

代码语言:txt
复制
void TRTCCloudCore::onEnterRoom(int result)
{
    if (MessageCallBack)
        MessageCallBack(TRTC_MSG_onEnterRoom, result, L"");
}

(7) Debug一下看看能不能回调到c#中

3. 让trtc sdk的视频在c#程序中显示

(1) 在c#程序窗口中,添加个button用来测试

Form1.cs

代码语言:txt
复制
private void button1_Click(object sender, EventArgs e)
{
            IntPtr hwnd = this.Handle;
            RTCWrapper.EnterRoom(0,
                "",
                "",
                0);
            RTCWrapper.StartLocalPreview(hwnd);
            RTCWrapper.StartLocalAudio();
}

(2) 用DllImport映射c++ dll中的接口StartLocalPreview()

TRTCWrapper.cs

代码语言:txt
复制
[DllImport("TRTCWrapper.dll", EntryPoint = "StartLocalPreview")]
public static extern void StartLocalPreview(IntPtr hwnd);

(3) 在TRTCWrapper.dll中实现StartLocalPreview()接口

TRTCWrapper.h

代码语言:txt
复制
//开启本地预览
extern "C" __declspec(dllexport) void _stdcall StartLocalPreview(HWND hwnd);

TRTCWrapper.cpp

代码语言:txt
复制
_declspec(dllexport) void _stdcall StartLocalPreview(HWND hwnd)
{
    if (trtcInstance)
        trtcInstance->startPreview(hwnd);
    //else 输出错误日志
}

(4) 调用trtc sdk本地视频预览接口

TRTCCloudCore.cpp

代码语言:txt
复制
void TRTCCloudCore::startPreview(HWND hwnd)
{
    if (m_pCloud == nullptr)
        return;
 
    if (m_bStartLocalPreview)
        return;
 
    if (!hwnd)
        return;
 
    m_pCloud->startLocalPreview(hwnd);
    m_bStartLocalPreview = true;
}

(5) 用相同的方法实现enterRoom、startLocalAudio

注意:

c#调用c++dll,因为是DllImport动态引用,所以debug时进不了c++代码;

可以写个简单的mfc exe,用静态引用的方式引用TRTCWrapper.lib和liteav.lib,就可以debug c++的代码了。

需要源码可以发邮件到tomas7571@qq.com

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、整体思路
  • 二、实现步骤
    • 1.  先写个从c#客户端调用c++ dll完成trtc初始化的功能
      • (1) 创建一个c#客户端(选择windowsform)项目
      • (2) 在程序入口main()函数中,加入InitWrapper()准备用来初始化trtc sdk
      • (3) 创建RTCManager.dll(选择.netframework库)c# 项目
      • (4) 创建RTCWrapper c#类,并用DllImport映射c++ dll中的接口InitWrapper()
      • (5) 创建TRTCWrapper.dll(选择动态链接库) c++项目
      • (6) 实现InitWrapper接口
      • (7) 在GetInstance()中加载trtc sdk的dll库,注意这里要用动态加载dll的方式,不然编译不过。Init()有其他作用,可以用来设置回调
    • 2. 接着实现sdk的回调通知给主程序
      • (1) 在程序入口main()函数中,加入AddTRTCMsgCallBack()准备用来注册trtc的回调
      • (2) 在RTCManager.dll中实现RTCDelegate c#类,用来接收trtc sdk的回调
      • (3) 用DllImport映射c++ dll中的接口AddTRTCMsgCallBack()
      • (4) 在TRTCWrapper.dll中实现AddTRTCMsgCallBack()接口
      • (5) 把messageCallback设置到trtc sdk中
      • (6) 在trtc sdk的回调接口onEnterRoom中调用messageCallback
      • (7) Debug一下看看能不能回调到c#中
    • 3. 让trtc sdk的视频在c#程序中显示
      • (1) 在c#程序窗口中,添加个button用来测试
      • (2) 用DllImport映射c++ dll中的接口StartLocalPreview()
      • (3) 在TRTCWrapper.dll中实现StartLocalPreview()接口
      • (4) 调用trtc sdk本地视频预览接口
      • (5) 用相同的方法实现enterRoom、startLocalAudio
相关产品与服务
实时音视频
实时音视频(Tencent RTC)基于腾讯21年来在网络与音视频技术上的深度积累,以多人音视频通话和低延时互动直播两大场景化方案,通过腾讯云服务向开发者开放,致力于帮助开发者快速搭建低成本、低延时、高品质的音视频互动解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档