quickjs使用事项

864 阅读2分钟

前言

使用网易的云信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);