面試的間隙回頭複習了一下node,感覺node就像一個膠帶,把V8和libuv粘在了一起。 V8毫無疑問,負責解析執行JavaScript,相當於語言層面的橋梁;而libuv則是負責操作系統底層功能的封裝,例如基於IOCP的event loop、file system、non-blockiong n ...
面試的間隙回頭複習了一下node,感覺node就像一個膠帶,把V8和libuv粘在了一起。
V8毫無疑問,負責解析執行JavaScript,相當於語言層面的橋梁;而libuv則是負責操作系統底層功能的封裝,例如基於IOCP的event loop、file system、non-blockiong network等。簡單來說node將兩者結合在一起,賦予JS操作底層方法的能力,擴大了這門語言的應用面。
其實之前一直在避開這個庫,因為有點難……至於為什麼突然又搞,因為之前已經把所有比較上層和簡單的模塊都寫完了,剩下的必須深入C++部分才能理解。比如說上篇timer模塊,其中的定時器執行依賴了內置模塊TimerWrap對象,這個對象……呃,如下:
TimerWrap(Environment* env, Local<Object> object) : HandleWrap(env, object, reinterpret_cast<uv_handle_t*>(&handle_), AsyncWrap::PROVIDER_TIMERWRAP) { int r = uv_timer_init(env->event_loop(), &handle_); CHECK_EQ(r, 0); }
不用懂這個,看到uv兩個小字母就知道這個定時器也是由libuv實現的,並且依賴於事件輪詢。
自己裝的逼,含淚也要寫完……遲早也需要看這個,不如開始吧。
這一節只講怎麼編譯啟動libuv,併在自己項目引入libuv庫(windows),雖然很簡單,但是搞了整整一天,異常痛苦,對於沒接觸過C++項目的我來說太難了。
萬事第一步,先下載源碼。跟node不一樣,直接去github上搞:https://github.com/libuv/libuv
然後是老樣子python2.6/2.7、vs2017那些,參照啟動node的步驟。
最後雙擊目錄的vcbuild,你會發現cmd視窗一閃而過,又出問題了。。。
當時我直接打開了那個bat文件,發現根本流程有點奇怪:
set target_env= @rem Look for Visual Studio 2017 only if explicitly requested. if "%target_env%" NEQ "vs2017" goto vs-set-2015 echo Looking for Visual Studio 2017
這裡的target_env根本沒定義,所以直接跳到尋找2015或更低版本的vs邏輯,並且上面的註釋說要精確指定?於是我直接在set那裡加上了=vs2017,理所當然的成功了。
但是,正確的方法是:打開當前目錄的cmd,輸入 vcbuild vs2017,回車
cmd會自動執行腳本,並把vs2017作為參數帶進去,然後那個target_env會被賦值……我也不知道為什麼只有2017要精確指定
這裡的sln生成特別快,在vs中打開這個解決方案,編譯運行生成一個debug文件夾。
直接講如何在空白C++項目中引入該庫,血淚教訓,不要問為什麼這麼做,反正能跑起來!
1、生成一個windows應用台控製程序
2、把libuv目錄下的include文件夾和debug/lib/libuv.lib文件都複製到自己項目的根目錄下
3、打開項目/屬性,然後在C/C++那點常規,在附加包含目錄添加一個include,如圖:
4、繼續選擇下麵的鏈接器/輸入,然後在附加依賴項添加一串lib:
libuv.lib Ws2_32.lib iphlpapi.lib Userenv.lib Psapi.lib advapi32.lib psapi.lib shell32.lib userenv.lib ws2_32.lib user32.lib
當時我只添加了一個libuv.lib,導致我流逝了了一晚上的生命,血虧。
做完這些,就可以嘗試寫一個demo跑一下了,測試代碼如下:
#include "uv.h" #include <iostream> uv_loop_t *loop; int main() { loop = uv_default_loop(); uv_run(loop, UV_RUN_DEFAULT); std::cout << "Hello World!\n"; }
不要問這個程式能幹啥,如果編譯後不報錯,那就是成功了。