Chrome中嵌入Qt窗口

先发个图镇楼。深度截图_google-chrome_20190829173047

了解几个概念

https://developer.chrome.com/native-client ,开始之前先看下这个文章,认识下Native Client是什么东西。

Native Client提供了一个沙盒机制在浏览器里面运行C/C++代码。有如下3中方式编译运行。

PNaCl

Portable Native Client,编译的目标为*.pexe。Portable如何解释,关键体现在编译的目标文件编译一次之后可以在Windows、Linux、Mac,甚至x86和arm上都可以运行。因为PNaCl方式是基于LLVM编译的,目标文件通过浏览器加载之后会通过浏览器内部集成的ahead-of-time (AOT) translator转换成对应平台的执行代码。这种方式可以不通过Chrome Web Store,直接通过页面指定就能够加载。

NaCl

non-portable Native Client,编译的目标文件为*.nexe。相对于PNaCl,这种方式编译的是平台无关,CPU架构相关,不同的CPU架构生产独立的执行文件。这样在加载的时候就不需要再次转换,相对于PNaCl,首次启动速度要更快。这种方式必须通过Chrome Web Store安装,或者在开发者模式下加载。

PPAPI

这个在文档中描述得比较隐晦,个人觉得有两个解释。一个是Native Client对应的一套接口,叫Pepper API。一个是Pepper plug-in,这种是通过gcc/g++编译生成的动态库文件,在不同系统、CPU都需要重新编译,可以通过浏览器加载成插件,如PPAPI版本的flash插件。

对于三种类型可以通过编译方式比较直观的有个认识:PNaCl是通过sdk中toolchain/linux_pnacl提供的编译工具编译的,目标文件是静态链接的;NaCl是通过sdk中toolchain/linux_x86_glibc(文档中还有clang-newlib)提供的编译工具编译,目标文件是动态链接的;PPAPI可以用平台的开发工具编译,如gcc,VS,XCode,相对PNaCl和Nacl可以链接sdk以外的函数。

开始Native Client之旅

先来个hello word

https://developer.chrome.com/native-client/devguide/tutorial/tutorial-part1,根据这篇文章下载sdk、编译、运行就可以开心的跑起来一个hello word程序,注意下浏览器版本高于sdk的版本就可以了。part2里面在Makefile里面添加TOOLCHAIN指定编译方式变量就可以体验PNaCl、NaCl和PPAPI了。我下载的sdk版本是pepper_49,编译PPAPI指定TOOLCHAIN=linux,和文档中描述不一样。

编译

运行了一个hello word之后,再对编译过程。https://developer.chrome.com/native-client/devguide/devcycle/building,这个里面对sdk里面的工具集有个详细介绍。

PNaCl和NaCl编译的基础是sdk中带的libc的库,如果需要链接其他第三方的都需要用sdk的编译工具编译成对应的版本,PNaCl编译成静态库,NaCl编译成动态库。这两种模式不能直接用系统自动的头文件或者库文件,否则会导致各种报错。.pexe可以通过pnacl-translate转换成不同CPU架构的.nexe。

PPAPI可以直接用平台的开发工具进行编译,只需要将nacl sdk中几个必要的接口实现,就可以通过浏览器加载了。这样编译不受nacl限制,但是运行还是会受到沙盒影响。我用open和libusb_get_version方法验证系统调用和第三方函数调用,结果如下:

PNaCl和NaCl对于open函数能够编译通过,但是运行的时候报Function not implemented的错误,libusb_get_version编译不通过。

PPAPI编译都能通过,浏览器开启沙盒的情况下运行open会提示Operation not permitted,带–no-sanbox运行能够成功创建文件,但是浏览器退出之后再打开又会提示(权限不够)。libusb_get_version运行正常。PPAPI虽然能够调用系统和第三方的函数,但沙盒限制的方法还是要用pepper API中替代的方法。

运行

PNaCl运行部署.nmf和.pexe就可以,这两个文件在编译的时候生产,只需要在页面的element添加src=”hello_tutorial.nmf”和type=”application/x-pnacl”就可以了。

Nacl相对PNaCl需要Chrome Web Store安装或者在开发者模式加载,这就需要manifest.json文件。manifest文件里面可以配置mimetype的名称。

PPAPI可以通过启动浏览器的参数注册插件信息:google-chrome-stable –ppapi-out-of-process –register-pepper-plugins=”$fullpath/ppapi_helloword.so;application/x-ppapi-demo” file://$fullpath/index.html

Qt for Native Client

https://blog.qt.io/blog/2015/09/25/qt-for-native-client-and-emscripten/,有了Native Client的基础之后,参考这个博客就可以把Qt窗口嵌入到chrome中了。文中用的Mac,Linux下面有少许差异。

下载Qt源码编译

源码地址https://code.qt.io/qt/qtbase.git,使用wip/nacl分支。
export NACL_SDK_ROOT=path-to-nacl_sdk/pepper_49 ,指定nacl sdk路径
./nacl-configure linux-pnacl Release ,配置编译环境,源码好像只支持pncal
make ,编译Qt源码。

编写测试程序

http://git@github.com:msorvig/qt-nacl-manualtests.git,这个里面有Qt for Native Client的测试程序。深度截图_选择区域_20190902133707

如上图代码,相比原生的Qt程序,就是将main函数替换成Q_WIDGETS_MAIN就可以了。

编译测试程序

/path/to/qmake && make。qmake用Qt for Native Client版本编译出来的,在qtbase/bin目录。

部署运行

qtbase/bin/nacldeployqt -o pnacl/ window_widgets.bc 。nacldeployqt是Qt for Native Client编译出来的工具,将make生成的目标文件部署成运行目录,包含页面、.nmf、.pexe。在浏览器中加载部署的页面就可以看到文中第一张图的效果。

存在的问题

1、PNaCl模式首次启动非常慢,因为需要转换成对应平台的执行文件。尝试讲Qt编译成NaCl版本,但是没有成功。可以通过pnacl-translate转换成NaCl的解决首次启动慢的问题。

2、键盘输入没有反应。最终确认是处理消息的窗口不是实际显示的窗口。

3、弹出对话框将主窗口完全遮挡。

4、……应该还有很多坑,还没有验证其他的特性。项目2016之后没有维护,基本只是处于demo状态,要达到我预想的需求还是有很大一步要走。看到希望也得到失望,先告一段落了。

 

给看完的同学留个彩蛋

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注