2013-01-03 86 views
3

我需要幫助將某些Objective C「代碼塊」方法轉換爲C++中的等效代碼。 請指教。將目標C「代碼塊」轉換爲C++中的等效代碼

A被用作代碼塊...

.h文件中定義..

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

用於一個.mm文件..

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

)^(無效* img) { //部分代碼...

  }); 
+0

C++世界呈現什麼樣的界面?在C++中,有三種不同的結構實現了「固定函數」的概念 - 有成員指針,函子和C風格函數指針。相關的Cocos2dx API期望哪一個? –

+0

它應該是C++風格的函數指針或接近上面給出的代碼片段的東西。 – user1908860

+0

是否提供'queueLoadImageWithBlock()'系統?如果是這樣,第二個參數的類型是什麼?如果它是一個塊,那麼用函數指針就無法滿足它。他們只是不相同。 –

回答

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*型的第二個參數,沒有第三個參數。至於invokation,存在回調對象生存期的問題。是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)); 
+2

-1:真的沒有理由推薦函數指針而不是函子。如果編寫一個模板的想法讓你感到害怕,那麼試試'std :: function'或者'boost :: function',這些工作可以直接使用。或者,地獄,拉姆達達。 – Puppy

+0

不完全正確。而gcc不支持C++ 11 lambda,clang(你應該使用這種方式)確實支持很多C++ 11特性,而lambda函數就是其中之一。 – Ahti

+0

你在吸菸嗎?海灣合作委員會有lambda。地獄,甚至* Visual Studio *都有lambda。 – Puppy

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]; 
}); 
+0

它的說法是:「名稱空間標準中沒有類型命名」功能「。我是否需要包含任何頭文件? – user1908860

+0

您可能應該使用此代碼工作的Xcode版本來限定該答案。 –

+0

這是''。 – Puppy

1

使用Apple的clang版本,您可以在C和C++以及Objective-C中使用塊。這顯然是非標準的C++,但是它工作。

由於lambdas可分配給塊(但不能以其他方式),因此可以在不更改被調用函數的情況下使用C++ lambda表達式。有關更多信息,請參閱this question