默认情况下,CEF 是/MT
,而Qt是/MD
那么,如果你没有去在意MT、MD选项,那么极大可能性,会遇到程序崩溃的问题,并且表象会误导你查明原因的方向。并且,更换多个IDE也无法查明原因。
例子
当加载网页后,想同步更新标题栏。
那么,你需要做的是,在CEF的OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString &title)
函数将title
传给Qt的控件,标题栏或者是QTabWidget。
比如,我这里最初的方案是,使用std::function + std::bind回调方式
// MainWindow.cpp
//设置回调
simpleHandler->SetTitleChangeCallback(
std::bind(&MainWindow::changeTittle, this, std::placeholders::_1, std::placeholders::_2));
// 关联两个信号
connect(this, &MainWindow::changeTitle, browserTabWidget,&BrowserTabWidget::changeTitle);
设置回调实现方式:
//SimpleHandler.h
using TittleChangeCallback = std::function<void(int index, QString)>;
void SetTitleChangeCallback(TittleChangeCallback cb)
{
tittleChangeCB = std::move(cb);
}
private:
TittleChangeCallback tittleChangeCB;
调用回调
//SimpleHandler.cpp
void SimpleHandler::OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString &title)
{
CEF_REQUIRE_UI_THREAD();
titleChangeCB(index, title);
}
一切看着都没什么问题,但是运行就会崩溃。
最初,怀疑是多线程下,可能需要加锁
但结果一致,还是崩溃。
那在CEF里传一个Qt对象进去发送信号呢
仍然一样,还是崩溃。
结论
后来,才明白原因,就是MT、MD的问题。将CEF的方式改为MD,同时由于Sandbox支持(链接 cef _ Sandbox.lib)只有在使用/MT 标志构建时才能使用。所以要禁用沙箱使用,运行带有附加命令行标志的 CMake-DUSE _ SANDBOX = Off。
这里,如果不把Sandbox 关闭的话,会出现以下报错
具体做法:
在Clion中可以在设置中的CMake这里进行设置,改为下图这样,即可成功编译。
其他工具,也是一样的,改MD、关Sandbox 。