前言
使用网易的云信PC客户端框架开发了有一段时间了,其中也改了不少其中的bug以及扩展了很多功能,但是长久以来一直有一个问题,那就是不能热更新。当出现问题的时候,只能通过重新打包安装才能进行解决,效率很慢。所以,最近花了点时间,接入了quickjs,让其拥有了热更新的能力。接下来就是我使用quickjs的一点心得体会。
netease-im/NIM_Duilib_Framework: 网易云信Windows应用开发框架。 (github.com)
quickjs
之所以使用quickjs,是因为考虑到性能的要求。使用云信这个框架,也是考虑到性能的要求才使用,因为它是基于duilib二次开发的。
注意点
初始化
const auto runtime_ = new qjs::Runtime;
const auto context_ = new qjs::Context(runtime_);
context_->SetUserData(this);
JS_SetModuleLoaderFunc(runtime_->runtime(), NULL, jsModuleLoader, NULL);
到处模块和到处子模块
auto module = context_->NewModule("DuiLib");
auto window = module->ExportWeakClass<JsWindow>("Window");
window.Init();
// 添加构造函数
window.AddCtor2<newWindow>();
// 添加js自定义方法
window.AddFunc<createWindow>("create");
读取文件
BYTE* ReadFileToBuffer(const wchar_t* filename, size_t& size) {
HANDLE hFile = ::CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return nullptr;
DWORD dwSize = ::GetFileSize(hFile, NULL);
if (dwSize == 0) return nullptr;
if (dwSize > 4096 * 1024) return nullptr;
DWORD dwRead = 0;
BYTE* pByte = new BYTE[dwSize + 1];
::ReadFile(hFile, pByte, dwSize, &dwRead, NULL);
::CloseHandle(hFile);
if (dwRead != dwSize) {
delete[] pByte;
pByte = nullptr;
}
// 结尾需要有结尾符号,不然quickjs会直接出现读取异常的错误
pByte[dwSize] = '\0';
size = dwSize;
return pByte;
}
c++绑定js函数
static qjs::Value findControl(JsWindow* pThis, qjs::Context& context, qjs::ArgList& args) {
const std::wstring name = nbase::UTF8ToUTF16(args[0].ToStdString());
const auto control = pThis->FindControl(name);
// 需要返回的控件都要实现返回classid
return qjs::WeakClass<ui::Control>::ToJsById(context, control->get_weak_ptr<ui::Control>(), control->GetClassId());
void RegisterLabel(qjs::Module* module)
{
auto label = module->ExportWeakClass<ui::Label>("Label");
// 绑定关系需要有父子关系
label.Init(qjs::WeakClass<ui::Control>::class_id());
label.AddCtor<createControl>();
label.AddFunc<setText>("setText");
}
c++访问js函数
if (this_.HasProperty("initWindow")) {
qjs::Value result = this_.Invoke("initWindow");
}
c++注册对象到js中
qjs::Value mgr = qjs::WeakClass<WindowEx>::ToJs(*context, get_weak_ptr<WindowEx>());
this_.SetProperty("manager", mgr);