前言 JS Extension
本課程,教你怎麼增加 Javscript 的 function,將自已常用的功能,用c code寫出來, 之後我就先稱之為 js extension,現在我們就來開發 js extension吧。
讀取 JS file
再寫 js extension之前,再重覆說明一下,如果讀取 Javascript File,可以參考上一課的內容 Script Run2 。
簡單講就是把 js 的了語法存到 v8::String 裡,當然你要怎麼去讀取 JS File 方法就很多種了,我不必再說明。
實作一個 mktime
Javascript 沒有 mktime的function,我們就先實作一個 mktime js estension吧!!
ObjectTemplate : 定義一個 function 給 Javascript 呼叫
建立一個 ObjectTemplate , 我們要先給 ObjectTemplate 指定一個 function 名稱,第二個參數是指定 C Code 中「執行的function」,接者再將新的 ObjectTemplate 傳送給 Context ( Context 就很像是瀏覽器的意思),所以我們現在就把 js extension 掛上了瀏覽器,之後執行 JS 編譯時,就可以正常使用這個 function了。
- Handle<ObjectTemplate> global;
- global = ObjectTemplate::New();
- //指定 mktime, c語言中執行的function也叫 mktime
- global->Set(String::New("mktime"), FunctionTemplate::New(mktime));
- Handle<Context> context;
- //將 ObjectTemplate 傳給 Context
- context= Context::New(NULL,global);
用 c語言寫一個 mktime function
建立一個 mktime function,參數這裡使用 Arguments的方式讓JS傳進來,這樣可以無限次的增加參數數量,反正 JS 沒有變數型態的問題,所以參數不用指定 char or int 等型態,回傳值型態為 Value ,Value 在 v8 中是全有變數型態的父類別,所以可以處理任何的變數型態,這裡的參數與回傳值只能用這兩個值,記住不能用別的數值,否則進編譯都過不了,這是為了配合 Javascript 的變數值。
記得在 get timestamp 時,時間是從 1900/01/01 開始計算的,所以傳入的日期要減掉 1900 ,月份在 c 語言中是從 0 開始計( 0 代表一月,11代表12月),所以月份也要記得減 1 ,然後說 Javascript 的月份也是從 0開始計,不過我還是習慣用1代表一月份啦,所以這裡我還是有減1,如果你需要配合舊的 Javascript 程式碼,月份的部份就要自已修改囉。
- Handle<Value> mktime(const Arguments& args)
- {
- unsigned int hours = args[0]->Uint32Value();
- unsigned int minutes = args[1]->Uint32Value();
- unsigned int seconds = args[2]->Uint32Value();
- unsigned int month = args[3]->Uint32Value();
- unsigned int day = args[4]->Uint32Value();
- unsigned int year = args[5]->Uint32Value();
- time_t t;
- struct tm timeinfo;
- memset(&timeinfo, 0, sizeof(tm));
- timeinfo.tm_sec = seconds;
- timeinfo.tm_min = minutes;
- timeinfo.tm_hour = hours;
- timeinfo.tm_mday = day;
- timeinfo.tm_mon = month-1;
- timeinfo.tm_year = year-1900 ;
- t = mktime(&timeinfo);
- return Uint32::New(t);
- }
C code main function
- #include <iostream>
- #include "v8.h"
- #include <time.h>
- Handle<Value> mktime(const Arguments& args);
- int main (){
- Handle<ObjectTemplate> global;
- HandleScope handle_scope;
- Handle<Context> context;
- global = ObjectTemplate::New();
- global->Set(String::New("mktime"), FunctionTemplate::New(mktime));
- context= Context::New(NULL,global);
- Context::Scope context_scope(context);
- //讀取 makeFunction.js ,並存到 String
- Handle<v8::String> source = ReadFile("makeFunction.js");
- //Compile
- Handle<Script> script = Script::Compile(source);
- Handle<Value> result = script->Run();
- //取得變數 result
- String::Utf8Value str(result);
- script = Script::Compile(String::New("result"));
- result = script->Run();
- cout << *String::Utf8Value(result);
- return 0;
- }
js code
現在就寫個 javascript 來測試一下 mktime功能
- var result = mktime(8,0,0,12,25,2011);
- //output : 1324771200