ไลบรารีส่วนหัวเท่านั้นเพื่อแสดงคลาส C++ และฟังก์ชันใน V8 เพื่อใช้ในโค้ด JavaScript v8pp ต้องการคอมไพเลอร์ที่รองรับ C++17 ห้องสมุดได้รับการทดสอบเมื่อ:
ไลบรารีมีชุดการทดสอบที่สามารถกำหนดค่า สร้าง และรันด้วย CMake:
~/v8pp$ mkdir out; cd out
~/v8pp/out$ cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON ..
~/v8pp/out$ make
~/v8pp/out$ ctest -V
รายการตัวเลือกโปรเจ็กต์ทั้งหมดสามารถแสดงรายการได้ด้วยคำสั่ง cmake:
~/v8pp/out$ cmake -LH ..
บางส่วนอาจเป็น:
// สร้างเอกสาร BUILD_DOCUMENTATION:BOOL=OFF
// สร้างไลบรารีที่ใช้ร่วมกัน BUILD_SHARED_LIBS:BOOL=ON
// สร้างและรันการทดสอบ BUILD_TESTING:BOOL=OFF
// ไลบรารีเฉพาะส่วนหัว V8PP_HEADER_ONLY:BOOL=0
// v8::แยกหมายเลขช่องข้อมูลที่ใช้ใน v8pp สำหรับข้อมูลที่แชร์ V8PP_ISOLATE_DATA_SLOT:STRING=0
// ชื่อขั้นตอนการเริ่มต้นปลั๊กอิน v8pp V8PP_PLUGIN_INIT_PROC_NAME:STRING=v8pp_module_init
// ส่วนต่อท้ายชื่อไฟล์ปลั๊กอิน v8pp V8PP_PLUGIN_SUFFIX:STRING=.dylib
// ใช้ V8 ABI ใหม่กับ V8_COMPRESS_POINTERS และ V8_31BIT_SMIS_ON_64BIT_ARCH V8_COMPRESS_POINTERS:BOOL=ON
v8pp รองรับเวอร์ชัน V8 หลังจาก 6.3 พร้อม v8::Isolate
การใช้งานใน API มี 2 เป้าหมายสำหรับการเชื่อมโยง:
v8pp::module
คลาส wrapper รอบ ๆ v8::ObjectTemplate
v8pp::class_
ซึ่งเป็น wrapper คลาสเทมเพลตรอบ ๆ v8::FunctionTemplate
ทั้งคู่ต้องการตัวชี้เพื่อ v8::Isolate
ซ์ อนุญาตให้ผูกจากโค้ด C++ เช่นรายการต่างๆ เช่น ตัวแปร ฟังก์ชัน ค่าคงที่ด้วยฟังก์ชัน set(name, item)
:
v8::Isolate* isolate;
int var;
int get_var () { return var + 1 ; }
void set_var ( int x) { var = x + 1 ; }
struct X
{
X ( int v, bool u) : var(v) {}
int var;
int get () const { return var; }
void set ( int x) { var = x; }
};
// bind free variables and functions
v8pp::module mylib (isolate);
mylib
// set read-only attribute
.const_( " PI " , 3.1415 )
// set variable available in JavaScript with name `var`
.var( " var " , var)
// set function get_var as `fun`
.function( " fun " , &get_var)
// set property `prop` with getter get_var() and setter set_var()
.property( " prop " , get_var, set_var);
// bind class
v8pp::class_<X> X_class (isolate);
X_class
// specify X constructor signature
.ctor< int , bool >()
// bind variable
.var( " var " , &X::var)
// bind function
.function( " fun " , &X::set)
// bind read-only property
.property( " prop " ,&X::get);
// set class into the module template
mylib.class_( " X " , X_class);
// set bindings in global object as `mylib`
isolate-> GetCurrentContext ()->Global()->Set(
v8::String::NewFromUtf8 (isolate, " mylib " ), mylib.new_instance());
หลังจากนั้นการเชื่อมโยงจะพร้อมใช้งานใน JavaScript:
mylib . var = mylib . PI + mylib . fun ( ) ;
var x = new mylib . X ( 1 , true ) ;
mylib . prop = x . prop + x . fun ( ) ;
ไลบรารีนี้เหมาะที่จะสร้างส่วนเสริม Node.js และ io.js ดูเอกสารเสริม
void RegisterModule (v8::Local<v8::Object> exports)
{
v8pp::module addon ( v8::Isolate::GetCurrent ());
// set bindings...
addon
. function ( " fun " , &function)
. class_ ( " cls " , my_class)
;
// set bindings as exports object prototype
exports-> SetPrototype (addon. new_instance ());
}
v8pp
- ไลบรารีแบบคงที่เพื่อเพิ่มฟังก์ชันส่วนกลางหลายอย่าง (โหลด/ต้องการบริบท JavaScript v8 require()
คือระบบสำหรับการโหลดปลั๊กอินจากไลบรารีที่แชร์test
- ไบนารีสำหรับการเรียกใช้ไฟล์ JavaScript ในบริบทซึ่งมีฟังก์ชันการโหลดโมดูล v8pp ให้ไว้ # include < iostream >
# include < v8pp/module.hpp >
namespace console {
void log (v8::FunctionCallbackInfo<v8::Value> const & args)
{
v8::HandleScope handle_scope (args. GetIsolate ());
for ( int i = 0 ; i < args. Length (); ++i)
{
if (i > 0 ) std::cout << ' ' ;
v8::String::Utf8Value str (args[i]);
std::cout << *str;
}
std::cout << std::endl;
}
v8::Local<v8::Value> init (v8::Isolate* isolate)
{
v8pp::module m (isolate);
m. function ( " log " , & log );
return m. new_instance ();
}
} // namespace console
V8PP_PLUGIN_INIT (v8::Isolate* isolate)
{
return console::init (isolate);
}
# include < v8pp/module.hpp >
# include < v8pp/class.hpp >
# include < fstream >
namespace file {
bool rename ( char const * src, char const * dest)
{
return std::rename (src, dest) == 0 ;
}
class file_base
{
public:
bool is_open () const { return stream_. is_open (); }
bool good () const { return stream_. good (); }
bool eof () const { return stream_. eof (); }
void close () { stream_. close (); }
protected:
std::fstream stream_;
};
class file_writer : public file_base
{
public:
explicit file_writer (v8::FunctionCallbackInfo<v8::Value> const & args)
{
if (args. Length () == 1 )
{
v8::String::Utf8Value str (args[ 0 ]);
open (*str);
}
}
bool open ( char const * path)
{
stream_. open (path, std::ios_base::out);
return stream_. good ();
}
void print (v8::FunctionCallbackInfo<v8::Value> const & args)
{
v8::HandleScope scope (args. GetIsolate ());
for ( int i = 0 ; i < args. Length (); ++i)
{
if (i > 0 ) stream_ << ' ' ;
v8::String::Utf8Value str (args[i]);
stream_ << *str;
}
}
void println (v8::FunctionCallbackInfo<v8::Value> const & args)
{
print (args);
stream_ << std::endl;
}
};
class file_reader : public file_base
{
public:
explicit file_reader ( char const * path)
{
open (path);
}
bool open ( const char * path)
{
stream_. open (path, std::ios_base::in);
return stream_. good ();
}
v8::Local<v8::Value> getline (v8::Isolate* isolate)
{
if ( stream_. good () && ! stream_. eof ())
{
std::string line;
std::getline (stream_, line);
return v8pp::to_v8 (isolate, line);
}
else
{
return v8::Undefined (isolate);
}
}
};
v8::Local<v8::Value> init (v8::Isolate* isolate)
{
v8::EscapableHandleScope scope (isolate);
// file_base binding, no .ctor() specified, object creation disallowed in JavaScript
v8pp::class_<file_base> file_base_class (isolate);
file_base_class
. function ( " close " , &file_base:: close )
. function ( " good " , &file_base::good)
. function ( " is_open " , &file_base::is_open)
. function ( " eof " , &file_base::eof)
;
// .ctor<> template arguments declares types of file_writer constructor
// file_writer inherits from file_base_class
v8pp::class_<file_writer> file_writer_class (isolate);
file_writer_class
. ctor <v8::FunctionCallbackInfo<v8::Value> const &>()
. inherit <file_base>()
. function ( " open " , &file_writer:: open )
. function ( " print " , &file_writer::print)
. function ( " println " , &file_writer::println)
;
// .ctor<> template arguments declares types of file_reader constructor.
// file_base inherits from file_base_class
v8pp::class_<file_reader> file_reader_class (isolate);
file_reader_class
. ctor < char const *>()
. inherit <file_base>()
. function ( " open " , &file_reader:: open )
. function ( " getln " , &file_reader:: getline )
;
// Create a module to add classes and functions to and return a
// new instance of the module to be embedded into the v8 context
v8pp::module m (isolate);
m. function ( " rename " , & rename )
. class_ ( " writer " , file_writer_class)
. class_ ( " reader " , file_reader_class)
;
return scope. Escape (m. new_instance ());
}
} // namespace file
V8PP_PLUGIN_INIT (v8::Isolate* isolate)
{
return file::init (isolate);
}
# include < v8pp/context.hpp >
v8pp::context context;
context.set_lib_path( " path/to/plugins/lib " );
// script can now use require() function. An application
// that uses v8pp::context must link against v8pp library.
v8::HandleScope scope (context.isolate());
context.run_file( " some_file.js " );
// Load the file module from the class binding example and the
// console module.
var file = require ( 'file' ) ,
console = require ( 'console' )
var writer = new file . writer ( "file" )
if ( writer . is_open ( ) ) {
writer . println ( "some text" )
writer . close ( )
if ( ! file . rename ( "file" , "newfile" ) )
console . log ( "could not rename file" )
}
else console . log ( "could not open `file'" )
console . log ( "exit" )
// Memory for C++ class will remain when JavaScript object is deleted.
// Useful for classes you only wish to inject.
typedef v8pp::class_<my_class> my_class_wrapper;
v8::Local<v8::Value> val = my_class_wrapper::reference_external(isolate, & my_class::instance ());
// Assuming my_class::instance() returns reference to class
// Memory for c++ object will be reclaimed by JavaScript using "delete" when
// JavaScript class is deleted.
typedef v8pp::class_<my_class> my_class_wrapper;
v8::Local<v8::Value> val = my_class_wrapper::import_external(isolate, new my_class);
ไลบรารีใช้มาโครตัวประมวลผลล่วงหน้าหลายตัว ซึ่งกำหนดไว้ในไฟล์ v8pp/config.hpp
:
V8PP_ISOLATE_DATA_SLOT
- v8::แยกหมายเลขช่องข้อมูล ใช้เพื่อจัดเก็บข้อมูลภายใน v8ppV8PP_PLUGIN_INIT_PROC_NAME
- ชื่อขั้นตอนการเริ่มต้นปลั๊กอินที่ควรส่งออกจากปลั๊กอิน v8ppV8PP_PLUGIN_SUFFIX
- ส่วนต่อท้ายชื่อไฟล์ปลั๊กอินที่จะถูกเพิ่มหากชื่อปลั๊กอินที่ใช้ใน require()
ไม่ได้ลงท้ายด้วยV8PP_HEADER_ONLY
- ใช้การดำเนินการเฉพาะส่วนหัวเท่านั้น ซึ่งเปิดใช้งานตามค่าเริ่มต้น