转 一个在cocos2d-x上用curl 下载数据功能

CCNetwork - any suggestions and comments are welcome :)

Added by Steve Kim about 1 month ago

Recently I am porting an app to cocos2d-x which I made for android, ios, bada, and qnx.

And realized that there is no simple way to get json object asynchronously.

So here, I am posting a class I have made. Please give me a feedback if there are some errors. Thank you.

CCNetwork.h

#include "cocos2d.h" 
#include "stdio.h" 
#include "stdlib.h" 
#include "curl.h" 
#include "pthread.h" 
#include "cJSON.h" 

namespace cocos2d
{
    class CCNetwork : public CCObject
    {
        SEL_CallFunc callback;
        SelectorProtocol *target;
        pthread_t threadInfo;
        char url[260];
        cJSON *cJSONResult;

        CCNetwork()
        {
            cJSONResult = NULL;
        }
    protected:
        static size_t writer( char *data, size_t size, size_t nmemb, string *writerData )
        {
            if(writerData == NULL)
                return 0;

            writerData->append(data, size * nmemb);
            return size * nmemb;
        }
    public:
        virtual ~CCNetwork()
        {
            if( cJSONResult != NULL )
            {
                freeResultJSON();
            }
        }

        static void *run( void *arg )
        {
            CCNetwork *network = (CCNetwork *)arg;
            CURL *curl;
            CURLcode res;
            int result = 1;
            string buffer;

            network->cJSONResult = NULL;

            curl_global_init( CURL_GLOBAL_ALL );

            curl = curl_easy_init();

            if( curl )
            {
                curl_easy_setopt( curl, CURLOPT_URL, network->url );
                curl_easy_setopt( curl, CURLOPT_FOLLOWLOCATION, 1L );
                curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, CCNetwork::writer );
                curl_easy_setopt( curl, CURLOPT_WRITEDATA, &buffer );

                res = curl_easy_perform( curl );

                curl_easy_cleanup( curl );

                if (res == 0)
                {
                    network->cJSONResult = cJSON_Parse( buffer.c_str() );

                    if( network->cJSONResult != NULL )
                        result = 0;
                }
            }

            ((network->target)->*(network->callback))();

            return (void *)result;
        }

        cJSON *getResultJSON()
        {
            int success;

            if( pthread_join( threadInfo, (void **)&success ) == 0 )
                return cJSONResult;
            else
                return NULL;
        }

        void freeResultJSON()
        {
            if( cJSONResult != NULL )
            {
                cJSON_Delete( cJSONResult );
                cJSONResult = NULL;
            }
        }

        static CCNetwork *loadJSON( const char *url, SelectorProtocol *target, SEL_CallFunc callback )
        {
            CCNetwork *network = new CCNetwork();

            if( network != NULL )
            {
                network->target = target;
                network->callback = callback;
                strcpy( network->url, url );

                if( pthread_create( &network->threadInfo, NULL, CCNetwork::run, network ) == 0 )
                {
                    network->autorelease();
                    return network;
                }

                CC_SAFE_DELETE( network );
            }
            return NULL;
        }
    };
}

callback function

void dataArrived() { isThreadRunning = false; }

the part which request url

isThreadRunning = true;
scheduleUpdate();
network = CCNetwork::loadJSON( "http://dodgemissile2.appspot.com/?count=10", this, callfunc_selector( YourNode::dataArrived ) );
network->retain();

update function
void YourNode::update( ccTime dt )
{
    if( !isThreadRunning )
    {
        if( network != NULL )
        {
            cJSON *result = network->getResultJSON();

            // process with result here

            network->release();
        }

        unscheduleUpdate();
    }
}

Replies (3)

Comment

RE: CCNetwork - any suggestions and comments are welcome :) - Added by Walzer Wang about 1 month ago

It will be a very useful class.
My suggestions when reviewing the code.

1. char url[260]; is danger, especially you dont' check the length before strcpy( network->url, url ), stack will easily overflow. I prefer to use std::string here to make it safe.

2. You like to use several return points in a function. It's not good when you would like to write some profile and test the performance. For example:


 static size_t writer( char *data, size_t size, size_t nmemb, string *writerData )
        {
            if(writerData == NULL)
                return 0;

            writerData->append(data, size * nmemb);
            return size * nmemb;
        }

The recommended approach is

 static size_t writer( char *data, size_t size, size_t nmemb, string *writerData )
        {
            // profile_start
            size_t retValue = 0;

            if(writerData != NULL)
            {
                  writerData->append(data, size * nmemb);
                  retValue = size * nmemb;
            }

            // profile_end. You have only one return point now
            return retValue;
        }


你可能感兴趣的:(curl,cocos2d-x,network,null,callback,string,comments,url)