Êã ï¾ç¿ï¾ Ê Golangããv8ã使ã
cgoã¨libv8ã使ã£ã¦ãã¿ã¤ãã«ã®ã¨ããã®ãã®ãä½ã£ã¦ã¿ããé å¼µãã°nodeã¿ãããªã®ãgoã§æ¸ããããï¾
ï½°ã
Êã ï¾ç¿ï¾ Ê cgo楽ãããシーコï¾ï½«ï½°
åºæ¬çãªæ¹æ³ã¯ä»¥ä¸ã®è¨äºã«ããã¨ããã ããv8ã®ãã¼ã¸ã§ã³ãä¸ãã£ã¦ãããããã®ã§ãå¤å°ã®æç´ãããã¦ããã
Embedding V8 Javascript Engine and Go | Brave New Method
ã³ã¼ãã¯ãã¹ã¦Githubã«ãã
yuroyoro/golang_v8_Embedding_sample · GitHub
ã¾ããlibv8ã使ã以ä¸ã®ãããªwrapperãc++ã§ç¨æãã¦ãcgoãã使ããããã«ãã¦ããã
#ifndef _V8WRAPPER_H #define _V8WRAPPER_H #ifdef __cplusplus extern "C" { #endif // compiles and executes javascript and returns the script return value as string char * runv8(const char *jssrc); #ifdef __cplusplus } #endif #endif // _V8WRAPPER_H
#include <v8.h> #include <string.h> #include "v8wrapper.h" using namespace v8; char * runv8(const char *jssrc) { // Get the default Isolate created at startup. Isolate* isolate = Isolate::GetCurrent(); // Create a stack-allocated handle scope. HandleScope handle_scope(isolate); // Create a new context. Handle<Context> context = Context::New(isolate); // Enter the context for compiling and running the hello world script. Context::Scope context_scope(context); // Create a string containing the JavaScript source code. Handle<String> source = String::New(jssrc); // Compile the source code. Handle<Script> script = Script::Compile(source); // Run the script to get the result. Handle<Value> result = script->Run(); // The JSON.stringify function object Handle<Object> global = context->Global(); Handle<Object> JSON = global->Get(String::New("JSON"))->ToObject(); Handle<Function> JSON_stringify = Handle<Function>::Cast(JSON->Get(String::New("stringify"))); Handle<Value> args[] = { result }; // stringify result Local<Value> json = JSON_stringify->Call(JSON, 1, args); // Convert the result to an UTF8 string and print it. String::Utf8Value utf8(json); // return result as string, must be deallocated in cgo wrapper return strdup(*utf8); }
runv8(char)ã¯ãå¼æ°ã®æååã®javascriptãv8ã§å®è¡ããçµæã®å¤ãJSON.stringifyããçµæã®æååãè¿ãã
ãªãããµã³ãã«ãªã®ã§ã¨ã©ã¼å¦çã¯ãã¦ããªã( ;ï¾ç¿ï¾)ã
ã§ãããã¤ãé©å½ã«makeããã以ä¸ã®makefileã¯osxç¨
V8_INC=/usr/local/Cellar/v8/3.19.18.4/include V8_LIBDIR=/usr/local/Cellar/v8/3.19.18.4/lib/libv8.dylib CC=g++ CFLAGS= -I$(V8_INC) -I/usr/include -lv8 -dynamiclib -o $(TARGET) SOURCES=v8wrapper.cc OBJECTS=$(SOURCES:.cc=.o) $(V8_DYLIB) TARGET=libv8wrapper.dylib all: $(TARGET) $(TARGET): $(OBJECTS) $(CC) $(CFLAGS) $< -o $@ clean: rm $(TARGET) $(OBJECTS)
ãã¨ã¯ãcgoã§ãã®v8warpperãlinkãã¦ä½¿ãã°ããã
package main // #cgo LDFLAGS: -L. -lv8wrapper -lv8 -lstdc++ // #include <stdlib.h> // #include "v8wrapper.h" import "C" import ( "encoding/json" "fmt" "unsafe" ) func RunV8(script string, result interface{}) error { // convert Go string to nul terminated C-string cstr := C.CString(script) defer C.free(unsafe.Pointer(cstr)) // run script and convert returned C-string to Go string rcstr := C.runv8(cstr) defer C.free(unsafe.Pointer(rcstr)) jsonstr := C.GoString(rcstr) fmt.Printf("Runv8 json -> %s\n", jsonstr) // unmarshal result err := json.Unmarshal([]byte(jsonstr), result) if err != nil { return err } fmt.Printf("Runv8 Result -> %T: %#+v\n", result, result) return nil }
RunV8ã§ã¯ã'encoding/json'ãå©ç¨ãã¦ãrunv8ã®æ»ãå¤ã§ããæååã®JSONããgoã®å¤ã«unmarshalããã
以ä¸ã®ããã«æååã§scriptãRunV8é¢æ°ã«æ¸¡ãã°interfaceåã§çµæãåå¾ã§ããã
package main import ( "fmt" ) func main() { scripts := []string{ "null", "true", "123", "457.78", "[10, 20, 30]", "'Hello, World'", "new Date()", `obj = {"foo": [1, 2], "bar": {"baz": true, "hoge": "fuga"}}`, } for _, s := range scripts { fmt.Printf("Script -> %s\n", s) var res interface{} RunV8(s, &res) fmt.Printf("Result -> %T: %#+v\n\n", res, res) } }
å®è¡çµæ
Script -> null Result -> <nil>: <nil> Script -> true Result -> bool: true Script -> 123 Result -> float64: 123 Script -> 457.78 Result -> float64: 457.78 Script -> [10, 20, 30] Result -> []interface {}: []interface {}{10, 20, 30} Script -> 'Hello, World' Result -> string: "Hello, World" Script -> new Date() Result -> string: "2014-06-11T08:58:43.951Z" Script -> obj = {"foo": [1, 2], "bar": {"baz": true, "hoge": "fuga"}} Result -> map[string]interface {}: map[string]interface {}{"foo":[]interface {}{1, 2}, "bar":map[string]interface {}{"baz":true, "hoge":"fuga"}}
ãã®ããã«ãJSONãstructã«mappingããããã¨ãã§ããã
package main import ( "fmt" ) type Foo struct { Foo []int `json:"foo"` Bar Bar `json:"bar"` } type Bar struct { Baz bool `json:"baz"` Hoge string `json:"hoge"` } func main() { script := `obj = {"foo": [1, 2], "bar": {"baz": true, "hoge": "fuga"}}` var result Foo fmt.Printf("Script -> %s\n", script) RunV8(string(script), &result) fmt.Printf("Result -> %T: %#+v\n", result, result) }
å®è¡çµæ
Script -> obj = {"foo": [1, 2], "bar": {"baz": true, "hoge": "fuga"}} Result -> main.Foo: main.Foo{Foo:[]int{1, 2}, Bar:main.Bar{Baz:true, Hoge:"fuga"}}