• 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
    ");
        }
    }
    
    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
    ");
        }
    }
    
    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
    ");
        }
    }
    
    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
    ");
        }
    }
    
    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
    ");
        }
    }
    
    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
    ");
        }
    }
    
    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
    ");
        }
    }
    
    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
    ");
        }
    }
    
    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
    ");
        }
    }
    
    
    
    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源码

  • 相关阅读:
    [转载]宇宙文明等级的划分标准
    常用的AJAX框架
    常用的AJAX框架
    【★】路由环路大总结!
    分销商城

    如何开始做外贸
    时间管理模型
    吕广渝:上帝视角看公司运营
    Java面试必问
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167336.html
Copyright © 2020-2023  润新知