c#客户端不能直接调用c++ dll,需要做2个黏合层把它们连接起来,这里以trtc sdk的dll为例
Program.cs
//初始化TRTC SDK
//调用链路:WindowsFormsApp1.exe(c#) -> RTCManager.dll(c#) -> TRTCWrapper.dll(c++) -> liteav.dll(c++,要调用的目标dll)
int nRet = RTCWrapper.InitWrapper();
TRTCWrapper.cs
public static class RTCWrapper
{
/// <summary>
/// 初始化TRTC
/// </summary>
/// <returns>1成功,0失败</returns>
[DllImport("TRTCWrapper.dll", EntryPoint = "InitWrapper")]
public static extern int InitWrapper();
}
TRTCWrapper.h
//初始化TRTC
extern "C" __declspec(dllexport) int _stdcall InitWrapper();
TRTCWrapper.cpp
_declspec(dllexport) int _stdcall InitWrapper()
{
trtcInstance = TRTCCloudCore::GetInstance();
if (trtcInstance)
{
trtcInstance->Init();
return 1;
}
else
return 0;
}
TRTCCloudCore.cpp
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
Program.cs
//注册SDK的callback
RTCDelegate rtcDelegate = new RTCDelegate();
RTCWrapper.AddTRTCMsgCallBack(rtcDelegate.rtcCallBack);
RTCDelegate.cs
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;
}
}
}
TRTCWrapper.cs
/// <summary>
/// 注册TRTC通用回调
/// </summary>
/// <param name="callback">通用回调</param>
/// <returns></returns>
[DllImport("TRTCWrapper.dll", EntryPoint = "AddTRTCMsgCallBack")]
public static extern void AddTRTCMsgCallBack(RTCWrapperCallback callback);
TRTCWrapper.h
//注册TRTC通用回调
extern "C" __declspec(dllexport) void _stdcall AddTRTCMsgCallBack(TRTCMsgCallback messageCallback);
TRTCWrapper.cpp
_declspec(dllexport) void _stdcall AddTRTCMsgCallBack(TRTCMsgCallback messageCallback)
{
if(trtcInstance)
trtcInstance->MessageCallBack = messageCallback;
//else 输出错误日志
}
TRTCCloudCore.h
typedef void(*TRTCMsgCallback)(int trtcModule, int errCode, const wchar_t* errMsg);
TRTCMsgCallback MessageCallBack = nullptr;
TRTCCloudCore.cpp
void TRTCCloudCore::onEnterRoom(int result)
{
if (MessageCallBack)
MessageCallBack(TRTC_MSG_onEnterRoom, result, L"");
}
Form1.cs
private void button1_Click(object sender, EventArgs e)
{
IntPtr hwnd = this.Handle;
RTCWrapper.EnterRoom(0,
"",
"",
0);
RTCWrapper.StartLocalPreview(hwnd);
RTCWrapper.StartLocalAudio();
}
TRTCWrapper.cs
[DllImport("TRTCWrapper.dll", EntryPoint = "StartLocalPreview")]
public static extern void StartLocalPreview(IntPtr hwnd);
TRTCWrapper.h
//开启本地预览
extern "C" __declspec(dllexport) void _stdcall StartLocalPreview(HWND hwnd);
TRTCWrapper.cpp
_declspec(dllexport) void _stdcall StartLocalPreview(HWND hwnd)
{
if (trtcInstance)
trtcInstance->startPreview(hwnd);
//else 输出错误日志
}
TRTCCloudCore.cpp
void TRTCCloudCore::startPreview(HWND hwnd)
{
if (m_pCloud == nullptr)
return;
if (m_bStartLocalPreview)
return;
if (!hwnd)
return;
m_pCloud->startLocalPreview(hwnd);
m_bStartLocalPreview = true;
}
注意:
c#调用c++dll,因为是DllImport动态引用,所以debug时进不了c++代码;
可以写个简单的mfc exe,用静态引用的方式引用TRTCWrapper.lib和liteav.lib,就可以debug c++的代码了。
需要源码可以发邮件到tomas7571@qq.com
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。