3

我需要帮助将一些 Objective C“代码块”方法转换为 C++ 中的等效方法。请指教。

A 被用作代码块...

在文件中定义.h..

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

在一个.mm文件中使用..

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

)^(void* img) { //一些代码...

            });
4

3 回答 3

2

最直接的比喻是std::function。这是一个被赋予签名的值类型(例如std::function<int(int)>,可以是适当签名的任何函数对象。可以在调用站点使用 lambda 代替块。

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];
});
于 2013-01-03T23:55:53.077 回答
1

使用 Apple 的 clang 版本,您可以使用 C 和 C++ 以及 Objective-C 中的块。这显然是非标准的 C++,但它确实有效。

您可以在不更改被调用函数的情况下使用 C++ lambda,因为 lambda 可以分配给块(但不能反过来)。有关更多信息,请参阅此问题

于 2013-01-05T00:18:59.077 回答
0

只要一个块的要求是你的而不是系统的。

就像我说的,有几种方法。函数指针需要最少的样板文件,但它们需要一个额外的参数来从调用者传递上下文(self在你的情况下)。函子和指向成员的指针通常需要模板机制才能工作,我们不要去那里。因此,使用函数指针,它的运行方式如下:

//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];
}

而且您必须修改 的原型queueLoadImageWithBlock以接受ResourceLoadObjFuncPtr参数而不是ResourceLoadObjCBlockCB,以及上下文的另一个参数(仅iconSlot在我们的例子中)。

并调用:

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

块是闭包——它们捕获声明它们的函数的变量。C++ 不提供 iOS 上的 GCC 支持的闭包(除了块)。因此,您必须手动将变量从函数范围传递给函数参数。在我们的例子中,如果我的假设是正确的,那么只有一个变量;在更复杂的情况下,您必须将它们包装在一个结构中并传递一个指向其中的指针。

另一种方法是使用抽象基类和通过其构造函数捕获上下文的具体实现。这将是这样的:

//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)
    {}
 };

queueLoadImageWithBlock等效项现在将采用类型的第二个参数,并且ResourceLoader*没有第三个参数。至于调用,存在回调对象生命周期的问题。是queueLoadImageWithBlock异步的——也就是说,它是否在调用回调之前返回?如果是这样,那么 MyResourceLoader 的本地实例将无法使用,您必须动态创建一个并以某种方式处置它。假设它是同步的(即在它返回后不调用回调):

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

如果不是:

[[GameViewController getInstance] getResourceLoadMediator]->
    queueLoadImageWithLoader([self.url UTF8String], new MyResourceLoader(self.iconSlot));
于 2013-01-03T22:49:44.043 回答