zoukankan      html  css  js  c++  java
  • cocos2d-x jsbinding 资源下载实现

        cocos2dx没有直接给出资源下载的api,可能是因为资源的管理每个项目的需求不太一样,所以完整的资源下载功能需要我们自己去实现。

        资源下载分为两部分,一部分是资源请求,另一部分是资源文件写入。资源请求模块,cocos2d-x封装了curl的功能,主要实现是extensions etwork下的几个类,通过他们我们可以方便的实现Http请求的功能。资源的写入主要是利用fwrite函数将数据流写入文件。完成了C++模块的实现以后,我们要做的是绑定到js,这样我们就可以在js端发起请求,将资源下载到手机。这里C++绑定还有Http请求的封装主要借鉴了https://github.com/akira-cn/cocos2dx-cqwrap/blob/master/cqwrap/src/scripting/cqwrap_httprequest_manual.cpp 我在此的基础上做了一些改动,同时增加了文件的写入功能

    #include "cqwrap_register_all_manual.h"
    
    #include "util/JsonHelper.h"
    
    #include "pattern/EventProxy.h"
    #include <algorithm>
    #include <sstream>
    
    
    #include "cocos-ext.h"
    // 这个用于获取各个平台的资源缓存缓存路径,关于缓存路径,请看http://www.cnblogs.com/hzd822/p/3258641.html
    #include "KT_ALL_PLATFORMS.h"
    
    
    USING_NS_CC_EXT;
    
    
    
    void js_register_cocos2dx_extension_httprequest(JSContext *cx, JSObject *global);
    
    JSClass  *jsb_HttpRequest_Class;
    
    JSObject *jsb_HttpRequest_prototype;
    
    
    
    void register_cqwrap_httprequest(JSContext* cx, JSObject* obj) {
    
        // first, try to get the ns
    
        jsval nsval;
    
        JSObject *ns;
    
        JS_GetProperty(cx, obj, "cc", &nsval);
    
        if (nsval == JSVAL_VOID) {
    
            ns = JS_NewObject(cx, NULL, NULL, NULL);
    
            nsval = OBJECT_TO_JSVAL(ns);
    
            JS_SetProperty(cx, obj, "cc", &nsval);
    
        } else {
    
            JS_ValueToObject(cx, nsval, &ns);
    
        }
    
        obj = ns;
    
    
    
        js_register_cocos2dx_extension_httprequest(cx, obj);
    
    }
    
    
    // 这个类对CCHttpRequest的封装
    class HttpRequest: public CCObject{
    
    protected:
    
        CCHttpRequest* m_request;
    
        std::vector<std::string> m_headers;
    
        int m_writefile;
    
        std::string m_url;
    
        struct xorStruct
    
        {
    
            xorStruct(char value) : m_value(value) {}
    
            char m_value;
    
            char operator()(char in) const { return in ^ m_value; }
    
        };
    
        
    
        void responseCallback(cocos2d::CCNode *sender, void *data){
    
            CCHttpResponse *response = (CCHttpResponse*)data; 
    
    
    
            if (!response) 
    
            { 
    
                CCLog("no response...");
    
                return; 
    
            } 
    
    
    
            int statusCode = response->getResponseCode(); 
    
            char statusString[64] = {}; 
    
            sprintf(statusString, "HTTP Status Code: %d", statusCode); 
    
            
    
            CCLOG("response code: %d", statusCode); 
    
    
    
            if (!response->isSucceed())  
    
            { 
    
                CCLOG("response failed"); 
    
                CCLOG("error buffer: %s", response->getErrorBuffer()); 
    
                
    
                JsonData* msg = new JsonData();
    
                (*msg)["data"] = response->getErrorBuffer();
    
                PROXY_FIRE("error", msg);
    
                CC_SAFE_DELETE(msg);
    
    
    
                return; 
    
            }
    
    
    
            JsonData* msg = new JsonData();
    
            // dump data 
    
            std::vector<char> *buffer = response->getResponseData();
    
            if (m_writefile == 1){
    
                // 获取相对路径
    
                std::string relativePath = m_url.substr(m_urlhostNum);
    
                std::string filePath;
    
                filePath = kt_library_path();
    
                #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
                    
                    filePath = filePath + "/Caches/";
                    
                #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    
                    filePath = filePath + "/Caches/";
    
                #endif
    
                filePath.append(relativePath);
    
                this->writeToFile(filePath.c_str(), *buffer);
    
                (*msg)["status"] = statusCode;
    
            }else{
    
                std::string buf(buffer->begin(),buffer->end());
    
                (*msg)["data"] = buf.c_str();
    
            }
    
    
    
            PROXY_FIRE("complete", msg);
    
            CC_SAFE_DELETE(msg);
    
        };
    
        
    
    public:
        int m_urlhostNum;
        
        void send(const char* buffer = NULL){
    
            if(m_request != NULL){
    
                if(NULL != buffer){
    
                    m_request->setRequestData(buffer, sizeof buffer);
    
                }
    
                m_request->setHeaders(m_headers);
    
                CCHttpClient::getInstance()->send(m_request);
    
                CC_SAFE_RELEASE_NULL(m_request);
    
                m_headers.clear();
    
            }
    
        };
    
        
        // 文件写入
        bool writeToFile(const char *filePath,std::vector<char> _responseData) {
    
            FILE* fout = fopen(filePath, "wb+");
    
            if (fout == NULL)
    
                return false;
    
            
    
            if (_responseData.size() > 0) {
    
                if (fwrite(&_responseData[0], sizeof(char), _responseData.size(), fout) != _responseData.size()) {
    
                    fclose(fout);
    
                    return false;
    
                }
    
            }
    
            
    
            fclose(fout);
    
            return true;
    
        }
    
        
    
        void setRequestHeader(std::string key, std::string content){
    
            if(m_request != NULL){
    
                key += ": ";
    
                key += content;
    
                m_headers.push_back(key);
    
            }
    
        };
    
        
    
        void setRequestData(std::string* requestData){
    
            if(m_request != NULL){
    
                m_request->setRequestData(requestData->c_str(),requestData->length());
    
            }
    
        };
    
        
    
        void open(CCHttpRequest::HttpRequestType type, const char* url,int writeFile){
    
    
    
            CC_SAFE_RELEASE_NULL(m_request);
    
            m_writefile = writeFile;
    
            m_request = new CCHttpRequest(); 
    
            m_request->setUrl(url);
    
            m_request->setRequestType(type);
    
            m_request->setResponseCallback(this, callfuncND_selector(HttpRequest::responseCallback));
    
            m_url = url;
    
        };
    
        HttpRequest(){
    
            m_request = NULL;
    
            m_headers = std::vector<std::string>();
    
            m_writefile = 0;
            
            m_urlhostNum = 32;
    
        };
    
        ~HttpRequest(){
    
            CC_SAFE_RELEASE_NULL(m_request);
    
        };
    
    };
    
    
    // 从这里开始是将C++类绑定到js,使js可以调用C++函数
    JSBool js_cocos2dx_extension_HttpRequest_setRequestHeader(JSContext *cx, uint32_t argc, jsval *vp){
    
        jsval *argv = JS_ARGV(cx, vp);
    
        JSObject *obj = JS_THIS_OBJECT(cx, vp);
    
        js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj);
    
        HttpRequest* cobj = (HttpRequest *)(proxy ? proxy->ptr : NULL);
    
        JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");
    
    
    
        if(argc == 2){
    
            std::string* key = new std::string();
    
    
    
            do {
    
                JSBool ok = jsval_to_std_string(cx, argv[0], key);
    
                JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
    
            } while (0);
    
    
    
            std::string* value = new std::string();
    
    
    
            do {
    
                JSBool ok = jsval_to_std_string(cx, argv[1], value);
    
                JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
    
            } while (0);
    
    
    
            cobj->setRequestHeader(*key, *value);
    
    
    
            JS_SET_RVAL(cx, vp, JSVAL_VOID);
    
    
    
            CC_SAFE_DELETE(key);
    
            CC_SAFE_DELETE(value);
    
    
    
            return JS_TRUE;    
    
        }
    
        JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1);
    
        return JS_FALSE;
    
    }
    
    
    
    JSBool js_cocos2dx_extension_HttpRequest_setRequestData(JSContext *cx, uint32_t argc, jsval *vp){
    
        jsval *argv = JS_ARGV(cx, vp);
    
        JSObject *obj = JS_THIS_OBJECT(cx, vp);
    
        js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj);
    
        HttpRequest* cobj = (HttpRequest *)(proxy ? proxy->ptr : NULL);
    
        JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");
    
        
    
        if(argc == 1){
    
            std::string* requestData = new std::string();
    
            
    
            do {
    
                JSBool ok = jsval_to_std_string(cx, argv[0], requestData);
    
                JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
    
            } while (0);
    
            
    
            
    
            cobj->setRequestData(requestData);
    
            
    
            JS_SET_RVAL(cx, vp, JSVAL_VOID);
    
            
    
            CC_SAFE_DELETE(requestData);
    
            
    
            return JS_TRUE;
    
        }
    
        JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0);
    
        return JS_FALSE;
    
    }
    
    
    
    JSBool js_cocos2dx_extension_HttpRequest_open(JSContext *cx, uint32_t argc, jsval *vp){
    
        jsval *argv = JS_ARGV(cx, vp);
    
        JSObject *obj = JS_THIS_OBJECT(cx, vp);
    
        js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj);
    
        HttpRequest* cobj = (HttpRequest *)(proxy ? proxy->ptr : NULL);
    
        JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");
    
    
    
        if(argc == 2 || argc == 3 || argc == 4){
    
            std::string* method = new std::string();
    
            
    
            do {
    
                JSBool ok = jsval_to_std_string(cx, argv[0], method);
    
                JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
    
            } while (0);
    
    
    
            std::string* url = new std::string();
    
    
    
            do {
    
                JSBool ok = jsval_to_std_string(cx, argv[1], url);
    
                JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
    
            } while (0);
    
    
            int writeFile = 1;
    
            if (argc == 3){
    
                do {
    
                    JSBool ok = jsval_to_int32(cx, argv[2], &writeFile);
    
                    JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
    
                } while (0);
    
            }
            
            int urlhostNum;
            if (argc == 4){
                do {
                    JSBool ok = jsval_to_int32(cx, argv[3], &urlhostNum);
    
                    JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
                    
                    cobj->m_urlhostNum = urlhostNum;
    
                } while (0);
    
            }
    
            
    
            if(*method == "POST"){
    
                cobj->open(CCHttpRequest::kHttpPost, url->c_str(),writeFile);
    
            }else{
    
                cobj->open(CCHttpRequest::kHttpGet, url->c_str(),writeFile);
    
            }
    
            JS_SET_RVAL(cx, vp, JSVAL_VOID);
    
            
    
            CC_SAFE_DELETE(url);
    
            CC_SAFE_DELETE(method);
    
    
    
            return JS_TRUE;    
    
        }
    
        JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1);
    
        return JS_FALSE;
    
    }
    
    
    
    JSBool js_cocos2dx_extension_HttpRequest_send(JSContext *cx, uint32_t argc, jsval *vp){
    
        jsval *argv = JS_ARGV(cx, vp);
    
        JSObject *obj = JS_THIS_OBJECT(cx, vp);
    
        js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj);
    
        HttpRequest* cobj = (HttpRequest *)(proxy ? proxy->ptr : NULL);
    
        JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object");
    
    
    
        if(argc == 1){
    
            std::string* data = new std::string();
    
            do {
    
                JSBool ok = jsval_to_std_string(cx, argv[0], data);
    
                JSB_PRECONDITION2( ok, cx, JS_FALSE, "Error processing arguments");
    
            } while (0);
    
    
    
            cobj->send(data->c_str());
    
            JS_SET_RVAL(cx, vp, JSVAL_VOID);
    
            CC_SAFE_DELETE(data);
    
            return JS_TRUE;    
    
        }
    
        if(argc == 0){
    
            cobj->send();
    
            JS_SET_RVAL(cx, vp, JSVAL_VOID);
    
            return JS_TRUE;    
    
        }
    
        JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1);
    
        return JS_FALSE;
    
    }
    
    
    
    JSBool js_cocos2dx_extension_HttpRequest_oncomplete(JSContext *cx, uint32_t argc, jsval *vp){
    
        JS_SET_RVAL(cx, vp, JSVAL_VOID);
    
        return JS_FALSE;
    
    }
    
    
    
    JSBool js_cocos2dx_extension_HttpRequest_onerror(JSContext *cx, uint32_t argc, jsval *vp){
    
        JS_SET_RVAL(cx, vp, JSVAL_VOID);
    
        return JS_TRUE;
    
    }
    
    
    
    void js_cocos2dx_extension_HttpRequest_finalize(JSFreeOp *fop, JSObject *obj){
    
    
    
    }
    
    
    
    JSBool js_cocos2dx_extension_HttpRequest_constructor(JSContext *cx, uint32_t argc, jsval *vp){
    
        if(argc == 0){
    
            HttpRequest* cobj = new HttpRequest(); 
    
            cocos2d::CCObject *_ccobj = dynamic_cast<cocos2d::CCObject *>(cobj);
    
            if (_ccobj) {
    
                _ccobj->autorelease();
    
            }
    
    
    
            TypeTest<cocos2d::extension::CCHttpRequest> t;
    
            js_type_class_t *typeClass;
    
            uint32_t typeId = t.s_id();
    
            HASH_FIND_INT(_js_global_type_ht, &typeId, typeClass);
    
            assert(typeClass);
    
            JSObject *obj = JS_NewObject(cx, typeClass->jsclass, typeClass->proto, typeClass->parentProto);
    
    
    
            JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
    
            // link the native object with the javascript object
    
            js_proxy_t *p;
    
            JS_NEW_PROXY(p, cobj, obj);
    
            JS_AddNamedObjectRoot(cx, &p->obj, "HttpRequest");
    
    
    
            return JS_TRUE;
    
        }
    
        JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0);
    
        return JS_FALSE;
    
    }
    
    
    
    void js_register_cocos2dx_extension_httprequest(JSContext *cx, JSObject *global) {
    
        jsb_HttpRequest_Class = (JSClass *)calloc(1, sizeof(JSClass));
    
        jsb_HttpRequest_Class->name = "HttpRequest";
    
        jsb_HttpRequest_Class->addProperty = JS_PropertyStub;
    
        jsb_HttpRequest_Class->delProperty = JS_PropertyStub;
    
        jsb_HttpRequest_Class->getProperty = JS_PropertyStub;
    
        jsb_HttpRequest_Class->setProperty = JS_StrictPropertyStub;
    
        jsb_HttpRequest_Class->enumerate = JS_EnumerateStub;
    
        jsb_HttpRequest_Class->resolve = JS_ResolveStub;
    
        jsb_HttpRequest_Class->convert = JS_ConvertStub;
    
        jsb_HttpRequest_Class->finalize = js_cocos2dx_extension_HttpRequest_finalize;
    
        jsb_HttpRequest_Class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);
    
    
    
        static JSPropertySpec properties[] = {
    
            {0, 0, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER}
    
        };
    
    
    
        static JSFunctionSpec funcs[] = {
    
            JS_FN("oncomplete",js_cocos2dx_extension_HttpRequest_oncomplete, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
    
            JS_FN("onerror",js_cocos2dx_extension_HttpRequest_onerror, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
    
            JS_FN("send",js_cocos2dx_extension_HttpRequest_send, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
    
            JS_FN("open",js_cocos2dx_extension_HttpRequest_open, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE),
    
            JS_FN("setRequestHeader",js_cocos2dx_extension_HttpRequest_setRequestHeader, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE),
    
    
            JS_FS_END
    
        };
    
    
    
        jsb_HttpRequest_prototype = JS_InitClass(
    
            cx, global,
    
            jsb_HttpRequest_prototype,
    
            jsb_HttpRequest_Class,
    
            js_cocos2dx_extension_HttpRequest_constructor, 0, // constructor
    
            properties,
    
            funcs,
    
            NULL, // no static properties
    
            NULL);
    
    
    
        // make the class enumerable in the registered namespace
    
        JSBool found;
    
        JS_SetPropertyAttributes(cx, global, "HttpRequest", JSPROP_ENUMERATE | JSPROP_READONLY, &found);
    
    
    
        // add the proto and JSClass to the type->js info hash table
    
        TypeTest<cocos2d::extension::CCHttpRequest> t;
    
        js_type_class_t *p;
    
        uint32_t typeId = t.s_id();
    
        HASH_FIND_INT(_js_global_type_ht, &typeId, p);
    
        if (!p) {
    
            p = (js_type_class_t *)malloc(sizeof(js_type_class_t));
    
            p->type = typeId;
    
            p->jsclass = jsb_HttpRequest_Class;
    
            p->proto = jsb_HttpRequest_prototype;
    
            p->parentProto = NULL;
    
            HASH_ADD_INT(_js_global_type_ht, type, p);
    
        }
    
    }
    

      绑定完之后,js的调用就很简单了

    // 创建http请求,请求远程图片
            var httpRequest = cc.HttpRequest();
            httpRequest.open('GET',fullPath);
            httpRequest.send();
            httpRequest.oncomplete = function (evt){
                if (evt.status == 200){
                    cc.log(fullPath+'------downLoad success');
                    // 下载成功
                }
            }
    
            httpRequest.onerror = function (evt){
                cc.log(fullPath+'------downLoad error');
                }
            }
    

      

  • 相关阅读:
    〖Linux〗转换Socks Proxy为Http Proxy
    〖Linux〗Linux的smb地址转换Windows格式(两者互转)
    〖前端开发〗HTML/CSS基础知识学习笔记
    精确光源(Punctual Light Sources)
    面元间的能量传输
    pbr若干概念
    c# xml 输出注释格式控制
    unity, 立即生效动画:Animation.sample()
    unity, 在材质上指定render queue
    unity, shader, Tags的位置
  • 原文地址:https://www.cnblogs.com/zhepama/p/3288574.html
Copyright © 2011-2022 走看看