zoukankan      html  css  js  c++  java
  • 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源码

  • 相关阅读:
    区别@ControllerAdvice 和@RestControllerAdvice
    Cannot determine embedded database driver class for database type NONE
    使用HttpClient 发送 GET、POST、PUT、Delete请求及文件上传
    Markdown语法笔记
    Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
    Mysql 查看连接数,状态 最大并发数(赞)
    OncePerRequestFilter的作用
    java连接MySql数据库 zeroDateTimeBehavior
    Intellij IDEA 安装lombok及使用详解
    ps -ef |grep xxx 输出的具体含义
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167336.html
Copyright © 2011-2022 走看看