摘要:本文轉載自眾成翻譯譯者亂發小生鏈接原文學習怎樣傳遞信息從到是一個非常難的事情。原因在于和兩種語言類型之間的巨大差異。你可以在這里查看所有的類型。這兩個組件松散和嚴格的表明一系列函數接收不同類型的參數,,,和和它們的返回值。
本文轉載自:眾成翻譯
譯者:亂發小生
鏈接:http://www.zcfy.cc/article/3360
原文:https://nodeaddons.com/type-conversions-from-javascript-to-c-in-v8/
學習怎樣傳遞信息從JavaScript到C++是一個非常難的事情。原因在于JavaScript和C++兩種語言類型之間的巨大差異。雖然C++是一門強類型語言("42"不是一個整數類型,它只是一個字符串!),JavaScript非常渴望幫我們轉換這些類型。
JavaScript語言包含 String,Numbers,Booleans,null,undefined這5種原始類型。V8使用繼承方式,JavaScript的類型都繼承于C++的Value,和Primitive的子類。除了標準的JavaScript語言之外,V8同時支持整型(Int32 and Uint32)。你可以在 這里查看所有的類型。
所有JavaScript值的引用都通過C++的Handle對象來保存-在大多數情況下是Local。Handle對象把運行中的JavaScript指向V8的存儲單元。你可以在我上一篇文章學習更多的存儲單元的知識。
當你通過API來為這些基礎單元工作時,你會注意到沒有分配Local對象很奇怪!這是有很重要的如以下三個原因:
JavaScript語句就是指向V8的存儲單元的。比如var x = 5; ,就是使X指向一個5的存儲單元,重新分配x=6并沒有改變這個存儲單元,它只是使x指向6.如果x和y都賦值為10,那么他們都指向同一個存儲單元。
2.函數調用值的傳遞,所以JavaScript 調用帶有參數的C++插件,如果這個值是一個原始類型數據,它始終是一個獨特的副本,改變它的值對調用的代碼沒有任何影響。
Handles(Local)都引用存儲單元,基于上述第一點,讓handle的值改變是沒有任何意義的,因為它的基本數據類型沒有變。
希望這是有道理的,然后你仍有可能修改V8的變量,我們只需要重新賦值給它。
幾個例子現在,讓我們看來一下Number 這種基本類型,當我們構建一個用JavaScript寫的C++插件,看看它會從JavaScript接收什么。我寫了一個C++PassNumber函數的例子:
void PassNumber(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); double value = args[0]->NumberValue(); value+= 42; Local retval = Number::New(isolate, value); args.GetReturnValue().Set(retval); }
完整的插件代碼在這里。
這個插件沒有做對函數的參數做任何處理,甚至它存不存在都不能保證。下面是相關的mocha測試,我們可以看到V8如果處理這些數字,更重要的是,其他輸入能不能轉成數字在JavaScript中。
describe("pass_number()", function () { it("return input + 42 when given a valid number", function () { assert.equal(23+42, loose.pass_number(23)); assert.equal(0.5+42, loose.pass_number(0.5)); }); it("return input + 42 when given numeric as a string", function () { assert.equal(23+42, loose.pass_number("23")); assert.equal(0.5+42, loose.pass_number("0.5")); }); it("return 42 when given null (null converts to 0)", function () { assert.equal(42, loose.pass_number(null)); }); it("return NaN when given undefined", function () { assert(isNaN(loose.pass_number())); assert(isNaN(loose.pass_number(undefined))); }); it("return NaN when given a non-number string", function () { assert(isNaN(loose.pass_number("this is not a number"))); });完整的類型轉換清單
我創建了一個git倉庫里面有類型轉換清單,我認為是非常有用的。為拿到它,獲取它:
`> git clone https://github.com/freezer333/nodecpp-demo.git`
建立這兩個組件,進入loose 和 strict 目錄,并執行在每個目錄執行 node-gyp configure build命令。首選你需要在全局安裝node-gyp。如果你完成了這兩步, 來看看這里。
> cd nodecpp-demo/conversion/loose > node-gyp configure build ... > cd ../strict > node-gyp configure build
The two addons (loose and strict) expose a series of functions that accept different types - Numbers, Integers, Strings, Booleans, Objects, and Arrays - and perform (somewhat silly) operations on them before returning a value. I’ve included a JavaScript test program that shows you the expected outputs of each function - but the real learning value is in the addons’ C++ code (strict/loose)
這兩個組件(松散和嚴格的)表明一系列函數接收不同類型的參數-Number,Integers,String,Booleans,Objects和Arrays和它們的返回值。我已經包含了JavaScript的測試程序,它會顯示每個函數的預期產出-但真正的學習值在插件C ++代碼(嚴格 / 寬松
在運行測試時,你需要先安裝 mocha,進入conversions 目錄(含 index.js):
`> npm test`
在“寬松”addons組件有很寬松的類型檢查-它基本上模仿純JavaScript函數將如何工作。例如,pass_string函數接受任何可能在JavaScript中轉換為字符串值,并返回它的倒序排列:
describe("pass_string()", function () { var str = "The truth is out there"; it("reverse a proper string", function () { assert.equal(reverse(str), loose.pass_string(str)); }); it("reverse a numeric/boolean since numbers are turned into strings", function () { assert.equal("24", loose.pass_string(42)); assert.equal("eurt", loose.pass_string(true)); }); it("return "llun" when given null - null is turned into "null"", function () { assert.equal("llun", loose.pass_string(null)); }); it("return "denifednu" when given undefined", function () { assert.equal(reverse("undefined"), loose.pass_string(undefined)); }); it("return reverse of object serialized to string", function () { assert.equal(reverse("[object Object]"), loose.pass_string({x: 5})); }); it("return reverse of array serialized to string", function () { assert.equal(reverse("9,0"), loose.pass_string([9, 0])); }); });
下面是字符串輸入的寬松轉換C ++代碼:
void PassString(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); v8::String::Utf8Value s(args[0]); std::string str(*s); std::reverse(str.begin(), str.end()); Local retval = String::NewFromUtf8(isolate, str.c_str()); args.GetReturnValue().Set(retval); }
所述“嚴格”的插件執行完整的類型和錯誤檢查,表現更像一個JavaScript C ++函數。對于所有的附加嚴格的方法,如果輸入和預期不相符合便會返回一個undefined。例如,pass_string函數的行為和寬松的解釋完全不同:
describe("pass_string()", function () { it("return reverse a proper string", function () { var str = "The truth is out there"; it("reverse a proper string", function () { assert.equal(reverse(str), strict.pass_string(str)); }); }); it("return undefined for non-strings", function () { assert.equal(undefined, strict.pass_string(42)); assert.equal(undefined, strict.pass_string(true)); assert.equal(undefined, strict.pass_string(null)); assert.equal(undefined, strict.pass_string(undefined)); assert.equal(undefined, strict.pass_string({x: 5})); assert.equal(undefined, strict.pass_string([9, 0])); }); });
void PassString(const FunctionCallbackInfo& args) { Isolate * isolate = args.GetIsolate(); if ( args.Length() < 1 ) { return; } else if ( args[0]->IsNull() ) { return; } else if ( args[0]->IsUndefined() ) { return; } else if (!args[0]->IsString()) { // This clause would catch IsNull and IsUndefined too... return ; } v8::String::Utf8Value s(args[0]); std::string str(*s); std::reverse(str.begin(), str.end()); Local retval = String::NewFromUtf8(isolate, str.c_str()); args.GetReturnValue().Set(retval); }
前往前進,下載查看完整的源代碼,并看看-該代碼是在/conversions目錄中。你會使用整數,布爾值,對象和數組見的例子。
Looking for more info?This post is actually a small excerpt from a book I’ve published - Node.js C++ Addons that covers this in detail. In it, you’ll also find equivalent code when using NaN. If you are interested, click here for the full contents and info on how to get your copy.
尋找更多信息?這篇文章實際上是從一本書,我已經出版了一本小摘錄- Node.js的C ++擴展中心覆蓋此詳細。在這里面,你還可以使用NaN當發現等效代碼。如果你有興趣,請點擊這里了解如何讓你的副本中的全部內容和信息。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/84848.html
摘要:類將源代碼解釋并構建成抽象語法樹,使用類來創建它們,并使用類來分配內存。類抽象語法樹的訪問者類,主要用來遍歷抽象語法樹。在該函數中,先使用類來生成抽象語法樹再使用類來生成本地代碼。 通過上一篇文章,我們知道了JavaScript引擎是執行JavaScript代碼的程序或解釋器,了解了JavaScript引擎的基本工作原理。我們經常聽說的JavaScript引擎就是V8引擎,這篇文章我們...
摘要:不允許隱式轉換的是強類型,允許隱式轉換的是弱類型。拿一段代碼舉例在使用調用函數的時候會先生成一個類模板運行時生成,執行的時候會生成類模板,執行的時候會生成類模板。 0 x 01 引言 今天和一個朋友討論 C++ 是強類型還是弱類型的時候,他告訴我 C++ 是強類型的,他和我說因為 C++ 在寫的時候需要 int,float 等等關鍵字去定義變量,因此 C++ 是強類型的,我告訴他 C+...
摘要:注意句柄棧并不是調用棧中的一部分,但句柄域卻在棧中。一個依賴于構造函數和析構函數來管理下層對象的生命周期。對象模板用來配置將這個函數作為構造函數而創建的對象。 如果你已經閱讀過了上手指南,那么你已經知道了如何作為一個單獨的虛擬機使用 V8 ,并且熟悉了一些 V8 中的關鍵概念,如句柄,域 和上下文。在本文檔中,還將繼續深入討論這些概念并且介紹其他一些在你的 C++ 應用中使用 V8 的...
摘要:前端日報精選中的組件通信問題詳解頁面的渲染過程面試中問什么問題加實現圖片前端壓縮并上傳用畫一個迷宮中文譯當不使用框架時瘋狂的技術宅在翻譯面向編程連續改造個網頁掘金周刊技術周刊期知乎專欄技術周刊包管理的前世今生眾成翻譯版發布 2017-07-31 前端日報 精選 React中的組件通信問題詳解 Weex 頁面的渲染過程面試中問什么React問題?HTML5 file API加canvas...
摘要:引擎可以用標準解釋器或即時編譯器來實現,即時編譯器以某種形式將代碼編譯為字節碼。這里的主要區別在于不生成字節碼或任何中間代碼。請注意,不使用中間字節碼表示法,不需要解釋器。這允許在正常執行期間非常短的暫停。 本系列的第一篇文章重點介紹了引擎,運行時和調用棧的概述。第二篇文章將深入V8的JavaScript引擎的內部。我們還會提供一些關于如何編寫更好的JavaScript代碼的技巧。 概...
閱讀 3487·2023-04-25 22:45
閱讀 1290·2021-11-11 16:54
閱讀 2797·2019-08-30 15:44
閱讀 3196·2019-08-30 15:44
閱讀 1654·2019-08-30 13:55
閱讀 948·2019-08-29 18:45
閱讀 1202·2019-08-29 17:25
閱讀 1016·2019-08-29 12:59