v8的初始化三部曲,前面花了三篇解決了第一步,由於只是生成了一個對象,第二步就是將其嵌入v8中,先看一下三個步驟。
// 生成默認Platform對象 std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform(); // 將其嵌入V8引擎內 v8::V8::InitializePlatform(platform.get()); // 初始化V8引擎 v8::V8::Initialize();
第一步可以由用戶自己手動實現platform,只要按照規范來繼承對應基類,一般也不會有人搞吧。
這里的嵌入,如果用代碼來進行解釋,實際上是叫做"命名空間"。v8引擎的體量非常巨大,所以需要有完善的規范來管理各個類。如果完整的閱讀過v8源碼,可以發現v8對類的邏輯管理用到了兩個方法,其中一個是命名空間,另外一個則是語義化宏。
先來看看命名空間的定義(對C++熟悉就很簡單了),如果只是跟我一樣的前端頁面仔,可以理解成模塊。舉一個例子,在前面一篇有一個類叫PageAllocator,在看源碼發現有兩個同名類,但是其中一個是掛在v8的命名空間下,另外一個則在v8::base的命名空間下,如下。
namespace v8 { class PageAllocator {} } namespace v8 { namespace base { class PageAllocator : public ::v8::PageAllocator {} } }
通過對v8命名空間所有類進行觀察,發現其所有的類都是一個基類,提供了聲明和一些虛函數,都是需要被繼承去實現的類。而對v8::base進行搜索時,發現了其命名空間下的所有方法都是實現類,可以看出,v8通過命名空間來對所有的class進行分類。
另外,其命名空間的名字也是有意義的,base命名空間下的類提供的功能都是比較底層的功能,比如說CPU、Hash、EnumSet等等。而之前那篇講的DefaultPlatform、TaskRunner,其命名空間都掛在v8::platform的下面。此外,WorkThread雖然從繼承關系上是屬於Thread類型,但是作為TaskRunner的內部類,實際上命名空間還是屬於platform,也就是只看命名空間就可以理解類的歸屬和功能。
比較典型的還有v8::debug包含垃圾回收、內存管理相關,v8::tracing包含調用棧追蹤的相關等等,這里就不一一舉例了。
除去命名空間,另外一個對類進行分類的就是語義化宏。這個命名是自己想的,主要是聯想到了語義化標簽,進行過格式化,實際上div和p在表現上並沒有什么區別,實際使用上只是為了語義化。同理,v8的很多宏會對類進行修飾,也是無意義的,純粹的語義化。
基本上所有的類都會有宏去修飾,還是拿之前的DefaultPlatform舉例。
// 宏定義 #define NON_EXPORTED_BASE(code) code #define V8_PLATFORM_EXPORT // 類聲明 class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {};
這里分別對實現類和基類都進行了修飾,V8_PLATFORM_EXPORT表明這個類是屬於platform模塊,且是一個實現類,可以輸出並使用。而NON_EXPORTED_BASE則表明該類不可直接使用,需要繼承實現。
宏的定義也給出來了,沒有任何意義,只是一個純粹的為了說明,跟注釋類似但是又有着不一樣的功能。
v8源碼的頭文件在類的定義上隨處可見這種宏,通過宏的名字就可以看出類的一些特征,從而方便調試和像我這樣無聊的人看源碼……
其實v8內部還有更多宏起着巨大的作用,比如在類聲明時,有時候需要禁掉這個類的拷貝構造函數和賦值功能,v8都把這個封裝到一個宏里,聲明的時候直接調用就行了,這些后面深入的時候再來細說把。