簡體   English   中英

如何處理來自C ++的objective-c委托?

[英]How to handle objective-c delegation from C++?

簡短版本:我有一個Qt / C ++,我不得不添加有限數量的Cocoa / Objective-C代碼。 我已將.cpp文件更改為.mm文件,並將objective-c代碼/對象添加到所述文件中,並進行編譯和工作。 我現在需要為我創建的一個對象 - 一個NSPopUpButton(或者更確切地說,它的菜單)代表一個委托 - 而且我被卡住了。 如何為此對象添加委托?

詳細信息:有問題的文件:

reportwindow.h,reportwindow.cpp更新為reportwindow.mm - 這些文件包含我原來的C ++實現和一些objective-c代碼(打開一個包含NSPopUpButton的NSSavePanel)。 reportwindow.h還包含在.cpp文件中,如果這有所不同。

menuHandler.h,menuHandler.mm - 這些文件包含一個(當前為空)的objective-c類,我打算將其用作委托

我的第一個想法是我可以簡單地將C ++類作為委托,但這顯然不起作用,因為直接的C ++不理解委托。 然后我想我將一個單獨的objective-c類作為NSMenuDelegate,並將它的一個實例添加為我的C ++類的成員對象。 由於我已經能夠添加其他objective-c對象作為成員,我認為這應該工作。 但是,只要我在C ++類頭文件中包含了我的新objective-c類的頭文件,我就會從蘋果頭文件(NSValue.h)中獲得幾百個關於“'''令牌之前的非預期不合格ID”的錯誤。 ,NSObject.h等)顯然這不起作用,至少不是原樣。 在我的類頭文件中包含任何cocoa頭時,我得到相同的結果。

然后我想我會嘗試使用objective-c類的前向聲明(這就是我讓其他Objective-c對象工作的方式)。 但是,這也沒有用 - 如果我將其聲明為“class myClassName”,我會收到一個關於將類重新定義為不同類型符號的錯誤(可能是c ++類vs objective-c協議)。 如果我嘗試將其聲明為@protocol myClassName,我會收到關於“'''令牌之前的預期unqualified-id”的錯誤。 那我怎么能做這個呢?

好的回答你的問題:

reportwindow.h還包含在.cpp文件中,如果這有所不同。

它的確有所作為。 觸摸Objective-C代碼的任何編譯單元(在本例中為cpp文件)都必須重命名為.mm或.m。 包括反過來包含C ++文件中的Objective-C內容的標題將導致C ++編譯器看到無法處理的Objective-C代碼的問題。

將cpp文件重命名為mm將在編譯期間選擇Objective-C選項(這不是文件命名為cpp或c時),因此允許使用Objective-C標記編譯內容(在您的情況下主要是“@”) 。

另一種方法是不將Objective-C委托類包含在C ++類中,而是在Objective-C委托中包含指向C ++類的指針(即以相反的方式實現它)。 這樣你就可以安排Objective-C代碼沒有觸及C ++代碼的東西。

編輯:其實,我更喜歡第二個建議。 這是一個例子:

DelegateClass.h:

class MyCPPClassHandlingStuff;

@interface MyDelegateObject : NSObject <SomeDelegateProtocol> {
  MyCPPClassHandlingStuff *m_handlerInstance;
}

- (id) initWithCPPInstance:(MyCPPClassHandlingStuff*)cppInstance;

- (void) theDelegateProtocolMethod;

@end

DelegateClass.mm

#include "MyCPPClassHandlingStuff.h"

@implementation MyDelegateObject

- (id) initWithCPPInstance:(MyCPPClassHandlingStuff*)cppInstance
{
  self = [super init];
  if (self) {
    m_handlerInstance = cppInstance;
  }
  return self;
}

- (void) theDelegateProtocolMethod
{
  if (m_handlerInstance)
    m_handlerInstance->handleDelegateMethod();
}

@end

以及MyCPPClassHandlingStuff.h:

#ifndef __MyCPPClassHandlingStuff_H__
#define __MyCPPClassHandlingStuff_H__

class MyCPPClassHandlingStuff
{
public:
  MyCPPClassHandlingStuff();
  void handleDelegateMethod();
};

#endif /* __MyCPPClassHandlingStuff_H__ */

MyCPPClassHandlingStuff可以從Objective-C初始化,但是你不能從那里用C ++代碼初始化任何Objective-C類。 如果需要在C ++代碼中使用Objective-C,則必須將其編譯為Objective-C(即使用.mm文件)。 我將.cpp細節作為練習留給讀者;)

創建一個Objective-C類來滿足委托協議,並讓它委托給您的C ++類。 問題是AppKit期望與Objective-C對象交談,因此您需要一個墊片來委托您的C ++對象。 (是的,你可以做一些運行時濫用,在你的C ++類中定義一個isa指針,使它與ObjC對象有點兼容(到你可以向C ++類發送消息的那一點),但不要這樣做。這很討厭。)

因此,制作一個使用C ++類初始化的墊片,將其作為ivar。 它應該實現您感興趣的委托方法,並以它能夠理解的方式將它們傳遞給您的C ++類。 田田,做完了。

有一些關於如何設置標題的有用信息,因此可以在ObjC和C ++中使用它們。 我可以在編譯和鏈接中將Objective C和/或C例程中的C ++主函數和類分開嗎?

然后我想我會嘗試使用objective-c類的前向聲明(這就是我讓其他Objective-c對象工作的方式)。 但是,這也沒有用 - 如果我將其聲明為“class myClassName”,我會收到一個關於將類重新定義為不同類型符號的錯誤(可能是c ++類vs objective-c協議)。

為什么不將它聲明為@class myClassName

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM