3

I need a help on converting some Objective C "code block" methods to the equivalent in C++. Please advise.

A is being used as code block...

Defined in .h file..

typedef void (^A)(void*); //argument is ptr to B

Used in one .mm file..

[[hello getInstance] getB]->queueLoadImageWithBlock([self.str UTF8String], (A

)^(void* img) { //some code...

            });
user1908860
  • 509
  • 1
  • 9
  • 19
  • What kind of interface does the C++ world present? In C++, there are three different constructs that implement the notion of a "canned function" - there are pointers-to-members, functors, and C-style function pointers. Which one does the relevant Cocos2dx API expect? – Seva Alekseyev Jan 03 '13 at 22:13
  • it should be c++ style function pointer or something close to above given code snippet. – user1908860 Jan 03 '13 at 22:19
  • Is `queueLoadImageWithBlock()` system-provided? If so, what's the type of its second parameter? If it's a block, there's no way you can satisfy it with a function pointer. They're just not equivalent. – Seva Alekseyev Jan 03 '13 at 22:26
  • yes..second parameter is blcok..and queueLoadImageWithBlock() is not system provided but written manually. I am okie if definition of queueLoadImageWithBlock() needs to be changed. But advise me how to achieve same functionality in c++. – user1908860 Jan 03 '13 at 22:33

3 Answers3

2

The most direct analogy is std::function. This is a value type that is given a signature (e.g. std::function<int(int)> and can be any function object of the appropriate signature. A lambda can be used in place of the block at the call site.

obj->queueLoadImageWithBlock(self.url, [](void* img)
{
    UIImage* img2 = (UIImage*)img;
    UIImageView* iv = [[UIImageView alloc] initWithImage:img2];
    iv.backgroundColor = [UIColor clearColor];
    [self.iconSlot addSubview:iv];
    iconLoaded(iv);
    [iv release];
});
Puppy
  • 144,682
  • 38
  • 256
  • 465
1

With Apple's version of clang you can use blocks in C and C++ as well as Objective-C. This is non-standard C++, obviously, but it works.

You can use C++ lambdas without changing the called function since lambdas are assignable to blocks (but not the other way around). See this question for more information.

Community
  • 1
  • 1
Ferruccio
  • 98,941
  • 38
  • 226
  • 299
0

As long as the requirement for a block is yours as opposed to system.

Like I said, there are several approaches. The function pointers require the least boilerplate, but they need an extra argument to pass the context from the caller (the self stuff in your case). Functors and pointer-to-members typically require template machinery to work, let's not go there. So with a function pointer, here's how it would go:

//Let's define a callback datatype
typedef void (*ResourceLoadObjFuncPtr)(void *, void*);
//argument 1 is ptr to ResourceLoadDescriptor, argument 2 is iconSlot, whatever it is

//Function that implements that type:
void MyLoad(void *img, void *iconSlot)
{
    UIImage* img2 = (UIImage*)img;
    UIImageView* iv = [[UIImageView alloc] initWithImage:img2];
    iv.backgroundColor = [UIColor clearColor];
    [(TheTypeOfIconslot*)iconSlot addSubview:iv];
    iconLoaded(iv);
    [iv release];
}

And you'd have to modify the prototype of queueLoadImageWithBlock to accept a ResourceLoadObjFuncPtr parameter instead of ResourceLoadObjCBlockCB, and another parameter for the context (just the iconSlot in our case).

And invoke:

[[GameViewController getInstance] getResourceLoadMediator]->
    queueLoadImageWithFunction([self.url UTF8String], MyLoad, self.iconSlot);

Blocks are closures - they capture the variables of the function where they're declared. C++ provides no closures that GCC on iOS supports (other than, well, blocks). So you'd have to pass the variables from the function scope to the function parameter by hand. In our case, if my assumptions are right, there's just one variable; in a more complex case, you'd have to wrap them in a structure and pass a pointer to one.

An alternative to that would be using an abstract base class and a concrete implementation that captures the context via its constructor. This would go like this:

//Callback type
class ResourceLoader
{
public:
    virtual void Load(void *) = 0;
};

//A callback implementation - not a function, but a class

class MyResourceLoader : public ResourceLoader
{
    IconSlotType *iconSlot;

    void Load(void *img)
    {
        //Same loader stuff as above
    }
public:
    MyResourceLoader(IconSlotType *isl)
    :iconSlot(isl)
    {}
 };

The queueLoadImageWithBlock equivalent would now take a second parameter of type ResourceLoader* and no third parameter. As for the invokation, there's the issue of callback object lifetime. Is queueLoadImageWithBlock asynchronous - that is, does it return before invoking the callback? If so, then a local instance of MyResourceLoader won't do, you'd have to create one dynamically and somehow dispose it. Assuming it's synchronous (i. e. does not invoke the callback after it returns):

MyResourceLoader ResLoader(self.iconSlot);
[[GameViewController getInstance] getResourceLoadMediator]->
    queueLoadImageWithLoader([self.url UTF8String], &ResLoader);

If it's not:

[[GameViewController getInstance] getResourceLoadMediator]->
    queueLoadImageWithLoader([self.url UTF8String], new MyResourceLoader(self.iconSlot));
Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • 2
    -1: There's really no reason to recommend function pointers over functors. If the idea of writing a template scares you, try `std::function` or `boost::function` which do this work out of the box. Or, hell, lambdas. – Puppy Jan 03 '13 at 23:53
  • not quite right. while gcc does not support c++11 lambdas, clang (which you should use either way) does support many c++11 features, and lambda functions is one of them. – Ahti Jan 03 '13 at 23:54
  • What are you smoking? GCC has lambdas. Hell, even *Visual Studio* has lambdas. – Puppy Jan 03 '13 at 23:56
  • excellent for a detailed explanation of all possible solution. This just not help me for a given question, rather clear my several doubts. You rock buddy :-) – user1908860 Jan 04 '13 at 21:59