Windows下vc开发chrome浏览器工程的一点粗浅理解和封装

Windows下vc开发chrome浏览器工程的一点粗浅理解和封装,第1张

Windows下vc开发浏览器工程的一点粗浅理解和封装
  • 一,封装包组成说明
  • 二,浏览器工程集成步骤
      • 1,创建一个合适的vc工程。

      • 2,将工程设置成unicode,静态库使用mfc。

      • 3,将SDK目录拷贝到合适的路径下(例如解决方案目录),在vc工程中添加SDK路径。

      • 4,在生成事件中添加对清单文件的添加。

      • 5,至此,vs工程的cef开发环境准备好了。

      • 6,将SDK中browser子目录中所有文件都添加到vc工程中。

      • 7,将引入工程的文件中(即browser子目录中的所有文件)所有.cc和.cpp文件修改“预编译头”为“不使用预编译头”。

      • 8,浏览器工程中主要用到的类,接口和引用的文件。

      • 9,需要说明的事情。

      • 10,至此,可以完整进行编译了。

      • 11,最终效果
  • 附录:
      • 1,关于Debug模式下_HAS_ITERATOR_DEBUGGING

本工程的cef内核基于中95版本(95.7.18+g0d6005e+chromium-95.0.4638.69)的官方32位release版本来作为范例的。

封装包是基于官方demo进行增删封装,链接如下:
封装包

一,封装包组成说明


Cef Resources,Cef的内核库和必须的资源文件,包含Debug版本和Release版本,分别在Debug和Release子目录中。

在调试和最后发行的时候,需要将对应的子目录中的所有文件拷贝到开发的Cef工程目录中。

SDK,包括浏览器内核的封装代码和两个清单文件,浏览器内核的库,另附加一个日志库。


browser,这个是对IE和Cef内核调用的一个封装,方便浏览器工程能尽量简单的使用。

两种内核,统一接口,并行存在。

third_party,包含cef的库以及log4cplus日志库。

库分Debug和Release版本。

二,浏览器工程集成步骤 1,创建一个合适的vc工程。

2,将工程设置成unicode,静态库使用mfc。

使用静态编译,是因为官方提供的发行版libcef.dll就是静态编译的。



然后确认工程的运行库是MTd(Debug编译)和MT(Release编译)。



3,将SDK目录拷贝到合适的路径下(例如解决方案目录),在vc工程中添加SDK路径。

头文件路径:

依赖库路径:

附加依赖项:

libcef.lib;libcef_dll_wrapper.lib;log4cplusUD.lib;comctl32.lib;rpcrt4.lib;shlwapi.lib;ws2_32.lib;cef_sandbox.lib;Advapi32.lib;dbghelp.lib;Delayimp.lib;OleAut32.lib;PowrProf.lib;Propsys.lib;psapi.lib;SetupAPI.lib;Shell32.lib;version.lib;wbemuuid.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib

其中log4cplusUD.lib是debug版,log4cplusU.lib是release版本。

对于uafxscwd.lib,libcmtd.lib,uafxcw.lib,libcmt.lib这四个文件的添加或者忽略与否,跟实际编译相关。

这几个文件是因为工程选择静态编译而可能需要采用下图中的方式进行配置的。





注意这四个运行时库文件的顺序。

4,在生成事件中添加对清单文件的添加。


命令行范例:

setlocal
mt.exe -nologo -manifest "$(SolutionDir)SDK/project.manifest" "$(SolutionDir)SDK/compatibility.manifest" -outputresource:"$(SolutionDir)bin/$(Configuration)/$(ProjectName).exe";#1
if %errorlevel% neq 0 goto :cmEnd
:cmEnd
endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
:cmErrorLevel
exit /b %1
:cmDone
5,至此,vs工程的cef开发环境准备好了。

另外,要将Cef Resources中的文件拷贝到vs工程对应的输出目录(exe输出目录)中,日志库的dll(SDK/third_party/log/log4cplus/lib)和配置文件(SDK/third_party/log/log4cplus/log.properties),也需要放在vs工程的输出目录中。

6,将SDK中browser子目录中所有文件都添加到vc工程中。

7,将引入工程的文件中(即browser子目录中的所有文件)所有.cc和.cpp文件修改“预编译头”为“不使用预编译头”。


选中引入文件中的所有.cc和.cpp,然后右键它们,选择“属性”-》“C/C++”-》“预编译头”-》“不使用预编译头”。

8,浏览器工程中主要用到的类,接口和引用的文件。

对于SDK中browser中的框架,简单描述下就是:
BaseBrowserLogger.h/.cpp,日志类BaseBrowserLogger。

它的接口全是静态函数,方便使用。

需要在vc工程代码的开始和结束之处分别调用BaseBrowserLogger::LogInit()和BaseBrowserLogger::LogRelease()。


BaseBrowserHelper.h/.cpp,掌控浏览器内核接口对象的工厂类BaseBrowserHelper.。

它包含一个自身的静态对象,方便在浏览器工程的不同窗口中直接调用其接口。


BaseBrowserLoader.h/.cpp,接口类BaseBrowserLoader,定义浏览器内核加载/释放接口。


BaseBrowserManager.h/.cpp,接口类BaseBrowserManager,定义浏览器窗口创建/关闭的接口,获取所有浏览器窗口列表的接口等,同时包含回调函数接口。


BaseBrowserWindow.h/.cpp,接口类BaseBrowserWindow,定义浏览器窗口常用功能的接口,如打开url,改变大小,设置窗口标题,跟页面执行js交互等,同时包含回调函数接口。


简单的说就是BaseBrowserHelper创建BaseBrowserLoader对象,而BaseBrowserLoader创建BaseBrowserManager对象,BaseBrowserManager创建BaseBrowserWindow对象。

9,需要说明的事情。

(1),cef
cef是一个多进程的库,通常包含一个browser进程和若干renderer进程,还有gpu进程和其他进程等等。



SDK并没有为cef库专门开发renderer等子进程,cef库就会默认直接将browser进程以传入命令行参数运行方式运行起来,作为各子进程。

任务管理器中,没有任何命令行参数的进程,就是browser进程,也就是主进程,关闭主进程,其他子进程也会一并自动关闭。


我们创建的vc工程,有自己的UI和代码逻辑,同时我们集成cef进来,创建浏览器窗口,对浏览器窗口进行 *** 作,这些都是应该在browser进程中执行的,也就是说,vc工程进程和cef的browser进程是同一个。

我们应当避免vc工程自己的UI和代码逻辑,在非browser进程中被执行,否则,就会出现同时开若干个vc工程的怪异情况。

简单的说就是,我们应当在vc工程代码的入口(例如main函数)判断当前进程是否browser进程(使用CefExecuteProcess函数的返回值来判断),如果不是,则直接退出,否则就正常进入vc工程代码循环以及cef代码循环。




SDK中将cef代码循环单独用一个工作线程来启动,避免跟vc工程代码循环相互影响,导致性能低下耦合度过高容易崩溃。

同时指定cef以单线程消息循环方式运行(multi_threaded_message_loop=0),也就是cef自己的UI线程(ClientHandler所在的线程,也即各种回调的线程)和其主线程(也即调用CefInitialize函数的线程)是同一线程,窗口的创建和各种回调都在同一个线程中处理。

虽然也可以设置cef以多线程消息循环方式(multi_threaded_message_loop=1),也就是UI线程和主线程不是同一个线程,使代码耦合度更低,只是这样,处理起来也越复杂,会出现大量跨线程函数调用和数据传递,目前可以暂不考虑。


另外,注意,SDK中的回调接口,是在cef的线程中被调用的,想要跟vc工程代码交互,就是一个跨线程的事情了。


最后,关于浏览器窗口的创建的一点说明。

SDK创建浏览器窗口时,会动态创建一个window(使用win32 api CreateWindowEx),然后将CefBrowserHost绑定到这个window上。

这个window的部分属性,通过BrowserWindowConfig 来设置。

这个window可以是一个独立的d出窗口,也可以作为子窗口依附在vc工程中创建的任何窗口中(dialog,view等)。

作为子窗口时,父窗口关闭的时候,注意要调用浏览器窗口的关闭,同理,父窗口改变大小的时候,也要调用浏览器窗口的改变窗口大小。



在所有cef浏览器窗口关闭之前,强行退出vs工程会导致cef报错,因此窗口退出前需要先close窗口。

(2),ie
略过。

尽管主体功能有了,并且能跟cef窗口同时存在,但是ie内核窗口不如cef窗口效率高,这里就不细说了。

各接口使用规则同上面cef的,毕竟封装包中已经简单封装了。

10,至此,可以完整进行编译了。


还有一个地方需要注意,在高版本(例如95版本)的cef工程中,Debug编译中添加了一个特别参数_HAS_ITERATOR_DEBUGGING,而92版本则没有这种问题。

不过,Release版本则没有这一问题。

关于这个地方,详见附录。

11,最终效果


附录: 1,关于Debug模式下_HAS_ITERATOR_DEBUGGING

定义迭代器在调试功能是否启用调试版本。

默认情况下,调试启用迭代器。

有关详细信息,请参阅调试迭代器支持。


若要启用迭代器调试调试版本中,将 _HAS_ITERATOR_DEBUGGING 设置为 1:
#define _HAS_ITERATOR_DEBUGGING 1
_HAS_ITERATOR_DEBUGGING 不能设置为 1。

零售版本。


若要禁用迭代器调试调试版本中,将 _HAS_ITERATOR_DEBUGGING 设置为 0:
#define _HAS_ITERATOR_DEBUGGING 0

95版本的cef和chromium的代码中,都在Debug编译的时候添加_HAS_ITERATOR_DEBUGGING编译参量,虽然可以把集成cef的工程中Debug编译时也添加这个参量以便顺利通过编译,但是,如果还引用其他第三方库,可能会出莫名其妙的问题。



上图是cef官方代码生成的工程里面的预处理器参数,可以看见Debug编译下包含了_HAS_ITERATOR_DEBUGGING,其实,官方下载的chromium文件中sandbox.lib的Debug版本都是用带有_HAS_ITERATOR_DEBUGGING进行编译的。


小结下就是这样的:
我们自己开发的整合cef的工程,Debug编译中,如果不指定_HAS_ITERATOR_DEBUGGING =0,就会报下面的错误。



如果指定了,也可能导致其他第三方库使用出现问题。


但是,如果我们将libcef_dll_wrapper工程的Debug编译参数中清除掉_HAS_ITERATOR_DEBUGGING =0,然后编译出新版,然后我们自己的工程,就不需要指定_HAS_ITERATOR_DEBUGGING了,如此就不影响其他第三方库的使用。

不过,如果我们的工程需要用到sandbox.lib,那就没法了。


当然了,这个_HAS_ITERATOR_DEBUGGING说了这么多,它只出现在Debug编译中。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/673370.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-19
下一篇 2022-04-19

发表评论

登录后才能评论

评论列表(0条)

保存