vu8 is a project that allows one to give JavaScript access to C++ classes and methods. The binding library is a header only library that uses template-metaprogramming extensively to make binding as easy as possible for the library user.
This library makes writing node.js modules that take advantage of C++ methods very easy but is also ideal for use in C++ systems where node.js is not required.
#include <vu8/Module.hpp>
namespace vu8 { namespace console {
v8::Handle<v8::Value> Println(const v8::Arguments& args) { ... }
void Flush() { std::cout.flush(); }
static inline v8::Handle<v8::Value> Open() {
v8::HandleScope scope;
Module mod;
return scope.Close(
mod("println", &Println)
.Set<void(), &Flush>("flush")
.NewInstance());
}
} }
extern "C" {
// vu8_module_init is the entry point
v8::Handle<v8::Value> vu8_module_init() {
return vu8::console::Open();
}
}
# The following line is neccesary before find_package(Vu8) if the vu8
# cmake files were not installed globally.
# set(CMAKE_MODULE_PATH <path containing FindVu8.cmake>)
find_package(Vu8) # find vu8, define vu8_plugin
if(NOT VU8_FOUND)
message(FATAL_ERROR "could not find vu8")
endif()
include_directories(${VU8_INCLUDE_DIRS})
vu8_plugin(module_name "source_file1.cpp;source_file2.cpp")
# the above will add the make target and cause the module to be
# installed into the vu8 module path
#include <vu8/Module.hpp>
#include <vu8/Class.hpp>
struct FileBase {
bool IsOpen() { return stream_.is_open(); }
bool Good() { return stream_.good(); }
bool Eof() { return stream_.eof(); }
void Close() { stream_.close(); }
protected:
std::fstream stream_;
};
struct FileWriter : FileBase {
bool Open(const std::string& file) { ... }
void Print(const v8::Arguments& args) { ... }
void Println(const v8::Arguments& args) { ... }
FileWriter(const v8::Arguments& args) { ... }
};
struct FileReader : FileBase {
FileReader(const std::string& file) { ... }
bool Open(char const *path) { ... }
};
bool Rename(char const *src, char const *dest) {
return ! std::rename(src, dest);
}
static inline v8::Handle<v8::Value> Open() {
v8::HandleScope scope;
vu8::Class<FileBase> fileBase;
fileBase.Set<void (), &FileBase::Close>("close")
.Set<bool (), &FileBase::Good>("good")
.Set<bool (), &FileBase::IsOpen>("is_open")
.Set<bool (), &FileBase::Eof>("eof")
;
// FileWriter inherits from FileBase
// Second template argument is a factory.. this one passes the
// v8::Arguments directly to FileWriter's constructor
vu8::Class<FileWriter, V8ArgFactory> fileWriter(fileBase);
fileWriter.Set<bool (const std::string&), &FileWriter::Open>("open")
.Set<void, &FileWriter::Print>("print")
.Set<void, &FileWriter::Println>("println")
;
// Print/Println take v8::Arguments directly so only the return type
// needs to be specified rather than the signature. Arguments and
// return types are converted from C++ to JS types and back for the
// user automatically based on the template method signatures.
// This factory calls FileReader's single argument constructor. It
// converts v8::Arguments to the appropriate c++ arguments.
vu8::Class<
FileReader, Factory<std::string const&>
> fileReader(fileBase);
fileReader.Set<bool (char const *), &FileReader::Open>("open");
// Can convert JS arguments to std::string/char const * and other types
// Code to setup other FileReader methods omitted for brevity
// Create a module to add classes and functions to and return a
// new instance of the module to be embedded into the v8 context
vu8::Module mod;
return scope.Close(
mod("Writer", fileWriter)
("Reader", fileReader)
.Set<bool(char const *, char const *), &Rename>("rename")
.NewInstance());
}
#include <vu8/Context.hpp>
vu8::Context ctxt;
// script at location jsFile can now use "vu8.load". An application
// that uses vu8::Context must link against libvu8.
ctxt.RunFile(jsFile);
// Load the file module from the class binding example and the
// console module.
var file = vu8.load('file'),
console = vu8.load('console')
var writer = new file.Writer("file")
if (writer.is_open()) {
writer.println("some text")
writer.close()
if (! file.rename("file", "newfile"))
console.println("could not rename file")
}
else console.println("could not open `file'")
console.println("exit")
// Memory for C++ class will remain when JavaScript object is deleted.
// vu8::NoFactory avoids creating any constructor for your C++ class from
// JavaScript, useful for classes you only wish to inject.
typedef vu8::Class<MyClass, vu8::NoFactory> classWrapper;
v8::Handle<v8::Value> val = classWrapper::ReferenceExternal(&MyClass::instance());
// Assuming MyClass::instance() returns reference to class
// Memory for c++ object will be reclaimed by JavaScript using "delete" when
// JavaScript class is deleted.
typedef vu8::Class<MyClass, vu8::NoFactory> classWrapper;
v8::Handle<v8::Value> val = classWrapper::ImportExternal(new MyClass());
% vu8bin file1.js file2.js # both files run with the same context