Google V8扩展利器发布:v8-native-binding-generator

用C++扩展Google V8很简单,但是类比较多时还是很烦的。前段时间开发cantk-runtime-v8时,我写了一个代码产生器v8-native-binding-generator,让扩展Google V8变得非常方便,甚至无需要了解V8本身。具体用法如下:

先写一个JSON的类描述文件,下面这段JSON是我用来模拟XMLHttpRequest的:

{
    "className":"HttpClient",
    "functions":[
        {
            "name":"send",
            "returnType" : "bool",
            "args"   : [
                {"name":"onProgress", "type":"function"},
                {"name":"onDone", "type":"function"}
            ]
        }
    ],
    "attributes" : [
        {"name":"url", "type":"string"},
        {"name":"returnType", "type":"string"},
        {"name":"method", "type":"string"},
        {"name":"requestHeaders", "type":"string"},
        {"name":"requestData", "type":"string"},
        {"name":"status", "type":"int32_t"},
        {"name":"statusText", "type":"string"},
        {"name":"responseHeaders", "type":"string"},
        {"name":"responseText", "type":"string"}
    ]
}

运行代码产生器:

node gen-v8-binding.js idl/http_client.json

生成4个文件,依次是HttpClient类的头文件和CPP文件,HttpClientBinding类的头文件和CPP文件:

HttpClient.h

#ifndef _HTTPCLIENT_H
#define _HTTPCLIENT_H

#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <v8.h>
#include <nan/nan.h>

using namespace std;
using namespace v8;

class HttpClient: public ObjectWrap {
public:
    HttpClient();
    ~HttpClient();

    bool send(NanCallback*  onProgress, NanCallback*  onDone);

    string getUrl() const;
    void setUrl(string url);

    string getReturnType() const;
    void setReturnType(string returnType);

    string getMethod() const;
    void setMethod(string method);

    string getRequestHeaders() const;
    void setRequestHeaders(string requestHeaders);

    string getRequestData() const;
    void setRequestData(string requestData);

    int32_t getStatus() const;
    void setStatus(int32_t status);

    string getStatusText() const;
    void setStatusText(string statusText);

    string getResponseHeaders() const;
    void setResponseHeaders(string responseHeaders);

    string getResponseText() const;
    void setResponseText(string responseText);

private:
    string _url;
    string _returnType;
    string _method;
    string _requestHeaders;
    string _requestData;
    int32_t _status;
    string _statusText;
    string _responseHeaders;
    string _responseText;
};

#endif

HttpClient.cpp

#include "HttpClient.h"
HttpClient::HttpClient(){
}

HttpClient::~HttpClient(){
}

bool HttpClient::send(NanCallback*  onProgress, NanCallback*  onDone) {
}

string HttpClient::getUrl() const {
    return this->_url;
}

void HttpClient::setUrl(string url) {
    this->_url = url;
}

string HttpClient::getReturnType() const {
    return this->_returnType;
}

void HttpClient::setReturnType(string returnType) {
    this->_returnType = returnType;
}

string HttpClient::getMethod() const {
    return this->_method;
}

void HttpClient::setMethod(string method) {
    this->_method = method;
}

string HttpClient::getRequestHeaders() const {
    return this->_requestHeaders;
}

void HttpClient::setRequestHeaders(string requestHeaders) {
    this->_requestHeaders = requestHeaders;
}

string HttpClient::getRequestData() const {
    return this->_requestData;
}

void HttpClient::setRequestData(string requestData) {
    this->_requestData = requestData;
}

int32_t HttpClient::getStatus() const {
    return this->_status;
}

void HttpClient::setStatus(int32_t status) {
    this->_status = status;
}

string HttpClient::getStatusText() const {
    return this->_statusText;
}

void HttpClient::setStatusText(string statusText) {
    this->_statusText = statusText;
}

string HttpClient::getResponseHeaders() const {
    return this->_responseHeaders;
}

void HttpClient::setResponseHeaders(string responseHeaders) {
    this->_responseHeaders = responseHeaders;
}

string HttpClient::getResponseText() const {
    return this->_responseText;
}

void HttpClient::setResponseText(string responseText) {
    this->_responseText = responseText;
}

HttpClientBinding.h

#ifndef _HTTPCLIENTBINDING_H
#define _HTTPCLIENTBINDING_H

#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>

#include <string.h>

#include <v8.h>
#include <nan/nan.h>

using namespace v8;
void HttpClientInitBinding(Handle<Object> target);

#endif

HttpClientBinding.cpp

#include "HttpClient.h"

#include "HttpClientBinding.h"

NAN_METHOD(newHttpClient) {
    NanScope();

    HttpClient* obj = new HttpClient();
    obj->Wrap(args.This());

    NanReturnValue(args.This());
}

NAN_METHOD(HttpClientSend) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());

    if(args.Length() == 2) {
        NanCallback* onProgress = new NanCallback(args[0].As<Function>());
        NanCallback* onDone = new NanCallback(args[1].As<Function>());

        bool retVal = obj->send(onProgress, onDone);
        NanReturnValue(NanNew<Boolean>(retVal));
        return;
    }

}

NAN_GETTER(HttpClientGetUrl) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<String>(obj->getUrl()));
}

NAN_SETTER(HttpClientSetUrl) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsString()) {
        v8::String::Utf8Value nativeValue(value);
        obj->setUrl(*nativeValue);
    }else{
        printf("invalid data type for HttpClient.url\n");
    }
}

NAN_GETTER(HttpClientGetReturnType) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<String>(obj->getReturnType()));
}

NAN_SETTER(HttpClientSetReturnType) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsString()) {
        v8::String::Utf8Value nativeValue(value);
        obj->setReturnType(*nativeValue);
    }else{
        printf("invalid data type for HttpClient.returnType\n");
    }
}

NAN_GETTER(HttpClientGetMethod) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<String>(obj->getMethod()));
}

NAN_SETTER(HttpClientSetMethod) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsString()) {
        v8::String::Utf8Value nativeValue(value);
        obj->setMethod(*nativeValue);
    }else{
        printf("invalid data type for HttpClient.method\n");
    }
}

NAN_GETTER(HttpClientGetRequestHeaders) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<String>(obj->getRequestHeaders()));
}

NAN_SETTER(HttpClientSetRequestHeaders) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsString()) {
        v8::String::Utf8Value nativeValue(value);
        obj->setRequestHeaders(*nativeValue);
    }else{
        printf("invalid data type for HttpClient.requestHeaders\n");
    }
}

NAN_GETTER(HttpClientGetRequestData) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<String>(obj->getRequestData()));
}

NAN_SETTER(HttpClientSetRequestData) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsString()) {
        v8::String::Utf8Value nativeValue(value);
        obj->setRequestData(*nativeValue);
    }else{
        printf("invalid data type for HttpClient.requestData\n");
    }
}

NAN_GETTER(HttpClientGetStatus) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<Int32>(obj->getStatus()));
}

NAN_SETTER(HttpClientSetStatus) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsInt32()) {
        int32_t nativeValue = value->Int32Value();
        obj->setStatus(nativeValue);
    }else{
        printf("invalid data type for HttpClient.status\n");
    }
}

NAN_GETTER(HttpClientGetStatusText) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<String>(obj->getStatusText()));
}

NAN_SETTER(HttpClientSetStatusText) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsString()) {
        v8::String::Utf8Value nativeValue(value);
        obj->setStatusText(*nativeValue);
    }else{
        printf("invalid data type for HttpClient.statusText\n");
    }
}

NAN_GETTER(HttpClientGetResponseHeaders) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<String>(obj->getResponseHeaders()));
}

NAN_SETTER(HttpClientSetResponseHeaders) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsString()) {
        v8::String::Utf8Value nativeValue(value);
        obj->setResponseHeaders(*nativeValue);
    }else{
        printf("invalid data type for HttpClient.responseHeaders\n");
    }
}

NAN_GETTER(HttpClientGetResponseText) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    NanReturnValue(NanNew<String>(obj->getResponseText()));
}

NAN_SETTER(HttpClientSetResponseText) {
    NanScope();
    HttpClient* obj = ObjectWrap::Unwrap<HttpClient>(args.This());
    if (value->IsString()) {
        v8::String::Utf8Value nativeValue(value);
        obj->setResponseText(*nativeValue);
    }else{
        printf("invalid data type for HttpClient.responseText\n");
    }
}

static Persistent<FunctionTemplate> constructor;
void HttpClientInitBinding(Handle<Object> target) {
    NanScope();
    Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(newHttpClient);
    NanAssignPersistent(constructor, ctor);
    ctor->InstanceTemplate()->SetInternalFieldCount(1);
    ctor->SetClassName(NanNew("HttpClient"));
    Local<ObjectTemplate> proto = ctor->PrototypeTemplate();

    proto->SetAccessor(NanNew("url"), HttpClientGetUrl, HttpClientSetUrl);
    proto->SetAccessor(NanNew("returnType"), HttpClientGetReturnType, HttpClientSetReturnType);
    proto->SetAccessor(NanNew("method"), HttpClientGetMethod, HttpClientSetMethod);
    proto->SetAccessor(NanNew("requestHeaders"), HttpClientGetRequestHeaders, HttpClientSetRequestHeaders);
    proto->SetAccessor(NanNew("requestData"), HttpClientGetRequestData, HttpClientSetRequestData);
    proto->SetAccessor(NanNew("status"), HttpClientGetStatus, HttpClientSetStatus);
    proto->SetAccessor(NanNew("statusText"), HttpClientGetStatusText, HttpClientSetStatusText);
    proto->SetAccessor(NanNew("responseHeaders"), HttpClientGetResponseHeaders, HttpClientSetResponseHeaders);
    proto->SetAccessor(NanNew("responseText"), HttpClientGetResponseText, HttpClientSetResponseText);

    NAN_SET_PROTOTYPE_METHOD(ctor, "send", HttpClientSend);

    target->Set(NanNew("HttpClient"), ctor->GetFunction());

}

目前支持的数据类型有:

* 1.string 字符串

* 2.int32_t 整数

* 3.int64_t 整数

* 4.double 浮点数

* 5.bool 布尔变量

* 6.function 回调函数(目前只能用于参数)

* 7.其它对象指针(如Image*),要求对象的类也是用本工具产生出来的。

更多例子请参考:https://github.com/drawapp8/cantk-runtime-v8

1.v8-native-binding-generator源码

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-24 04:49:06

Google V8扩展利器发布:v8-native-binding-generator的相关文章

GitLab v8.11.5 发布,代码托管平台

GitLab v8.11.5 发布了. 该版本主要改进如下: - Optimize branch lookups and force a repository reload for Repository#find_branch - Fix member expiration date picker after update - Fix suggested colors options for new labels in the admin area. !6138 - Fix GitLab imp

Chrome V8系列--浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略[转]

V8 实现了准确式 GC,GC 算法采用了分代式垃圾回收机制.因此,V8 将内存(堆)分为新生代和老生代两部分. 一.前言 V8的垃圾回收机制:JavaScript使用垃圾回收机制来自动管理内存.垃圾回收是一把双刃剑,其好处是可以大幅简化程序的内存管理代码,降低程序员的负担,减少因 长时间运转而带来的内存泄露问题. 但使用了垃圾回收即意味着程序员将无法掌控内存.ECMAScript没有暴露任何垃圾回收器的接口.我们无法强迫其进 行垃圾回收,更无法干预内存管理 内存管理问题:在浏览器中,Chrom

GitLab v8.11.6 发布,代码托管平台

GitLab  8.11.6 版本发布,同时社区版 (CE) 和企业版 (EE) 也做了更新. GitLab是一个利用 Ruby on Rails 开发的开源应用程序(腾云科技ty300.com),实现一个自托管的 Git 项目仓库(基础教程qkxue.net),可通过Web界面进行访问公开的或者私人项目. 本次更新内容如下: CE/EE: Fix unnecessary horizontal scroll area in pipeline visualizations. (!6005) CE/

Google Protobuf扩展字段使用

背景说明 Google Protobuf中不支持数据结构的派生关系,因此,如果在存在派生体系的对象中定义数据结构时,通过组合方式对数据结构进行组合,则需要对基类对象提供的通用接口进行重载或在外部进行动态转型才能达到获取或设置数据的目的. 因此考虑使用Google Protobuf提供的extension扩展机制解决数据结构之间的不能派生的问题,以此来达到减少重复工作量和便于维护代码的目的. 使用说明 定义公共数据类型 描述: 此数据类型为对象派生体系同基类提供的公共数据类型 示例: 1 // 公

Facebook发布React Native,用JavaScript开发移动原生应用

React.js Conf 2015会议上,Facebook发布了React Native,可以基于目前大热的开源JavaScript库React.js来开发iOS和Android原生App.而且React Native已经用于生产环境——Facebook Groups iOS应用就是基于它开发的.Facebook也已确认,这个项目很快将会开源. 根据ProgVille的文章,React Native的原理是,在JavaScript中用React抽象操作系统原生的UI组件,代替DOM元素来渲染,

Google Developers中国网站发布!(转)

Google Developers 中国网站是特别为中国开发者而建立的,它汇集了 Google 为全球开发者所提供的开发技术资源,包括 API 文档.开发案例.技术培训的视频.并涵盖了以下关键开发技术和平台产品的信息: 1. Android:   developer.android.google.cn Android 开发者官方网站面向应用开发者提供了 Android SDK 以及开发相关的各类文档.2. Web: developers.google.cn/web 学习如何利用 Progress

使用google搜索的利器

打开这个链接 https://www.modern.ie/en-us/tools,下载remote IE 东亚版本. 其实就是个remote app ,用你的微软帐号登录. 速度还不错,不过好像不能输入中文,这个有点麻烦. 不过一般搜中文还是用百度的多. 大家可以试试. google之类的都能用. 我是雷锋,不谢. 要200字......................................................................................

一个获取google chrome扩展crx文件信息的PHP操作类

此类中实现了从crx文件获取扩展的Appid.获取manifest.json文件内容.将crx文件转换为一般zip文件 代码如下: <?php class CrxParserException extends Exception { } /** * Chrome crx 解析器,用于获取扩展.皮肤ID * */ class CrxParser { const MAX_PUBLIC_KEY_SIZE = 65535; const MAX_SIGNATURE_SIZE = 65535; const

在Android上使用Google V8 JS 引擎

在cantk-runtime中直接使用的webview,通过JAVA扩展接口把Canvas的2d Context的API定向到JNI,通过OpenGL来图形加速,渲染速度大大提高.后来测试发现在大部分手机上都很正常,但是在有的老手机上速度不稳定,出现突然卡顿的情况.经过研究发现原因是老版本的webkit里没有requestAnimationFrame这个接口(或类似接口),用setTimeout来模拟的requestAnimationFrame非常不稳定. 为了解决这个问题,我们决定像其它Run