ext js如何动态更改xtype_如何自己做一个 React Native(二):尝试 Qt

关键的链接

Qt 是一个 C++ 的跨平台 UI 框架。要使用 Qt 的 UI 组件,首先要实现的就是,通过原生模块调起 Qt。

在 C++ 的世界里,模块的概念比较模糊,大家一般是采用动态链接库的形式来进行模块复用的。什么是动态链接库呢,在 Windows 上,形形色色的xxx.dll就是动态链接库。在 macOS 和 Linux 上,也各自有自己的动态链接库,比如xxx.dylibxxx.so

熟悉 Node.js 的朋友要问了,动态链接库是怎么工作的,和 npm 模块是什么区别?

动态链接库这个东西,其实是一组函数的封装,里面装的是二进制代码。它是一种特殊的可执行程序,特殊在哪呢?普通的可执行程序的入口点在main函数上,因此操作系统的 shell 知道如何唤起,但动态链接库则通常没有固定的入口点,它完全是开发者自己约定的,因此无法通过类似双击的形式执行。

这样的可执行程序,主要是用来存放需要共享的代码,操作系统中同一个动态链接库通常只需要在内存中驻留一份。只要不主动更改动态链接库的接口,那么它就可以被无缝地更新。Linux 上常用的一种做法就是对于libstdc++.6.so这样的库,不直接进行引用,而是再创建一个软连接,比如libstdc++.so,这样如果更新到了libstdc++.6.0.1.so,只需要修改软连接即可,而库本身因为不修改接口,因此依然可用。这种接口不变的机制,是二进制兼容性(binary compatibility)的根本。

6d03fd54319718c4e9c949035f0bb384.png

Qt和其他C++库一样,发行时会携带若干动态链接库。如果要想调用Qt的功能,虽然Qt官方做了非常多的外围工作,例如提供 moc、qmake 之类的工具,但实际只需要正确地链接好Qt的动态链接库即可。

在C++世界里,编译器本身只是套件当中我们最熟知的一个部分,它负责把人类的代码变成机器码。如果一个C++工程当中有4个cpp文件,那么一般会产生4个对应的机器码文件。而最终将这4个机器码文件合并起来的,则是链接器。不同的编译器,实际会有不同的编译套件。Windows 开发者比较熟悉的 vc++,对应的链接器实际是link.exe;而 gcc 则对应的链接器是ld;到了 LLVM 平台,就是lld了。

链接动态链接库的过程,也是由链接器来负责的。如果编译器明确知道你要调用的函数来自于某个动态链接库,而不是你自己的代码,那么编译时就会将这个符号对应的实体预留下来,到了链接期,链接器会在系统中查找对应的库。在 Node.js 原生模块的编译体系里,链接什么样的库,可以写在 gyp 文件当中。

关键环节如下:

"include_dirs": [
  "<!(node -e "require('nan')")",
  "D:/Qt/5.10.0/msvc2017_64/include/",
  "D:/Qt/5.10.0/msvc2017_64/include/QtCore"
],
"link_settings": {
  "libraries": [
    "D:/Qt/5.10.0/msvc2017_64/lib/Qt5Core.lib"
  ],
},

这里这个选项将会告诉链接器,我最终需要链接Qt5Core.dll这个库。

这里稍微说一下链接都需要什么。链接器进行链接的过程,最关键的是一个查找符号的过程。所谓符号,在这里就是我们需要调用的函数。编译器在工作时,为了能将符号确定下来,就需要相应的头文件。而链接器在链接时,为了能找到对应的符号,则需要一个“符号导出表”,这个表在 Windows 平台当中,常被写作.lib文件。一旦链接完成,运行程序时,系统则会去找对应的.dll文件了。

0e4176ebeb1cb34fb37737053ece27ac.png

因此,整个过程的顺利完成,需要头文件、lib文件和dll文件,三者缺一不可。

上面的gyp文件改动,我们增加了头文件和lib文件的查找范围。而对于dll文件,因为是运行时查找,因此不需要我们提供给 gyp ,只需要我们在运行 Node.js 之前,把对应的文件放在系统的默认查找位置上即可。

初试Qt

Qt当中功能非常多,如果我只是想验证一下调用 Qt 的能力,那么选择一个比较基础的功能即可。我选择的是调用QString相关的方法。

关键代码:

static NAN_METHOD(GetValue) {
  Hello* obj = ObjectWrap::Unwrap<Hello>(info.Holder());
  QString str = QString("%1 wants to be %2.").arg("Trump", "the president");
  auto bytes = str.toUtf8();
  auto v8Str = Nan::New<v8::String>(bytes.data()).ToLocalChecked();
  info.GetReturnValue().Set(v8Str);
}

其中QString就是 Qt 的私货了,我在这创建了一个实例,然后使用了插值,并将结果转化成了 V8 自己的字符串格式,最后作为了getValue()的返回值。

QString的定义主要放在QString头文件中,因此addon.cc的顶端我还增加了这个头文件:

#include <QString>

在Qt中,绝大部分类名都有自己对应的头文件。

现在,只要将Qt5Core.dll复制到index.js的旁边,就可以用node index.js调起整个程序了,其输出应该如下:

hello, Trump wants to be President.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值