0

I am porting a game using native C++ for Android. I need to know which method I should use to achieve the same functionality as NSURLConnection and NSURLRequest in only C++. Also how to get all the following delegate functions implemented for C++.

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

-(void)connectionDidFinishLoading:(NSURLConnection *)connection

Please advise.

user1908860
  • 509
  • 1
  • 9
  • 19
  • I was going to answer with Boost ASIO( http://www.boost.org/doc/libs/1_52_0/doc/html/boost_asio.html ), but that will only get you as far as TCP/IP. Handling the headers/requests isn't that difficult but it isn't a replacement for NSURLConnection. Wt C++( http://webtoolkit.eu ) has classes based on Boost ASIO, called Http::Client, that may be of interest too. Wt is great, but I cannot use it as an answer as I haven't used the web client portion yet. – Beached Dec 21 '12 at 16:34

2 Answers2

1

There is no way to implement Objective-C delegate methods in C++ directly. The best you can really hope to do is to use Objective-C++ to make a C++ object with an instance variable that is an Objective-C object whose sole purpose is to be the NSURLConnection delegate and forward those method calls to the owning C++ object. The C++ object should own/retain the Objective-C object, and be responsible for plugging it in as the delegate of the NSURLConnection object.

An extremely naive implementation of the above described pattern might look like this:

URLConnection.h

#ifndef __Cplusplus__URLConnection__
#define __Cplusplus__URLConnection__

#include <string>

class URLConnection
{
public:
    URLConnection(std::string url);
    ~URLConnection();

    void DidReceiveResponse(const void* response);
    void DidReceiveData(const void* data);
    void DidFailWithError(std::string error);
    void DidFinishLoading();

    void* mNSURLConnection;
    void* mDelegate;
};

#endif /* defined(__Cplusplus__URLConnection__) */

URLConnection.mm

#include "URLConnection.h"

@interface PrivateNSURLConnectionDelegate : NSObject <NSURLConnectionDelegate>
{
    URLConnection* mParent;
}
- (id)initWithParent: (URLConnection*) parent;
@end

@implementation PrivateNSURLConnectionDelegate

- (id)initWithParent: (URLConnection*) parent
{
    if (self = [super init])
    {
        mParent = parent;
    }
    return self;
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    mParent->DidReceiveResponse(response);
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    mParent->DidReceiveResponse(data.bytes);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    mParent->DidFailWithError(std::string([[error description]UTF8String]));
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    mParent->DidFinishLoading();
}

@end


URLConnection::URLConnection(std::string url)
{
    this->mDelegate = [[PrivateNSURLConnectionDelegate alloc] initWithParent: this];
    NSURLRequest* req = [NSURLRequest requestWithURL: [NSURL URLWithString: [NSString stringWithUTF8String: url.c_str()]]];
    this->mNSURLConnection = [[NSURLConnection alloc] initWithRequest: req delegate: (id)this->mDelegate];
}

URLConnection::~URLConnection()
{
    [(NSObject*)this->mNSURLConnection release];
    [(NSObject*)this->mDelegate release];
}

void URLConnection::DidReceiveResponse(const void* response)
{
    // Do something...
}
void URLConnection::DidReceiveData(const void* data)
{
    // Do something...

}
void URLConnection::DidFailWithError(std::string error)
{
    // Do something...
}

void URLConnection::DidFinishLoading()
{
    // Do something...
}

At the end of the day, NSURLConnection is an Objective-C object. There's no way to interact with it without using Objective-C.

Anusha Kottiyal
  • 3,855
  • 3
  • 28
  • 45
ipmcc
  • 29,581
  • 5
  • 84
  • 147
  • You mean to say mix of obj C and c++ code ? I need to this for Android using Cocos2dx and there everything has to be in pure C++. – user1908860 Dec 21 '12 at 00:35
  • Then you will not be able to use NSURLConnection, or any other iOS framework classes. I would suggest looking into a cross platform networking library. I'm sure plenty of them exist, but I work mostly with iOS/MacOS, so I'm not equipped to make a well-informed suggestion. – ipmcc Dec 21 '12 at 00:37
  • i see. I would wish someone else would have done through the same problem and got some help that how to do in c++. I am calling those :-) – user1908860 Dec 21 '12 at 01:19
  • Ultimately, you can write networking code against the low-level socket API on both platforms, but that is going to require significant effort to replicate the functionality provided by `NSURLConnection`. A better approach might be using libcurl. I found this question about bootstrapping it on Android: http://stackoverflow.com/questions/11330180/porting-libcurl-on-android-with-ssl-support and this question describes building it for iOS: http://stackoverflow.com/questions/9039554/using-libcurl-on-ios-5-as-an-alternative-to-nsurlconnection This might be one way to go. – ipmcc Dec 24 '12 at 17:13
  • 1
    Alternately, you might try writing a new question of the form "What is a good cross-platform networking library for iOS and Android?" (Although please don't edit this question -- doing so would significantly change it's meaning and remove any value from the answer/comments.) – ipmcc Dec 24 '12 at 17:16
0

LibCURL is maybe the best-known library for cross-platform C/C++ implementation of handling network/internet connections. If you combine it with an asynch technology like threads, you can begin to simulate NSURLConnection.

See here [https://curl.haxx.se/libcurl/c/multithread.html] for an example. You'll have to create a class that manages the CURL reference and an appropriate std::function delegate, that you will call when the connection finishes/errors/aborts etc. When using it, you can pass C++14 lambda functions to act as stand-ins for Objective C delegates.

Luc Bloom
  • 1,120
  • 12
  • 18