Short version: I have a Qt/C++ to which I am having to add a limited amount of Cocoa/Objective-C code. I have changed the .cpp file to a .mm file and added the objective-c code/objects to said file, and it compiles and works. I now need a delegate for one of the objects I created- a NSPopUpButton (or, rather, the menu thereof) to be exact - and I'm stuck. How can I add a delegate for this object?
简短的版本:我有一个Qt/ c++,我需要添加少量Cocoa/Objective-C代码。我已经将.cpp文件更改为.mm文件,并将objective-c代码/对象添加到该文件中,它将编译并工作。我现在需要为我创建的其中一个对象创建一个委托——一个NSPopUpButton(或者,更确切地说,是它的菜单)——我被卡住了。如何为该对象添加委托?
Details: Files in question:
细节:文件的问题:
reportwindow.h, reportwindow.cpp RENAMED TO reportwindow.mm -These are the files containing my original C++ implementation plus some objective-c code (open a NSSavePanel containing a NSPopUpButton). reportwindow.h is additionally included in a .cpp file, if that makes a difference.
reportwindow。h,reportwindow。cpp reportwindow重命名。mm -这些文件包含我最初的c++实现和一些objective-c代码(打开一个包含NSPopUpButton的NSSavePanel)。reportwindow。h被另外包含在.cpp文件中,如果这有什么不同的话。
menuHandler.h, menuHandler.mm -these files contain a (currently empty) objective-c class that I was intending to use as a delegate
menuHandler。h,menuHandler。mm -这些文件包含一个(当前为空的)objective-c类,我打算将其用作委托
My first thought was that I could simply make the C++ class the delegate, but this obviously doesn't work as straight C++ doesn't understand delegation. I then thought I'd make a separate objective-c class as a NSMenuDelegate and add an instance of it as a member object to my C++ class. As I have been able to add other objective-c objects as members, I figured this should work. However, as soon as I included the header for my new objective-c class in the C++ class header file, I got several hundred errors about "expected unqualified-id before '@' token" -from the apple header files (NSValue.h, NSObject.h, etc) So apparently that didn't work, at least not as-is. I get the same result when including ANY cocoa header in my class header file.
我的第一个想法是,我可以简单地将c++类作为委托,但这显然不能作为直接的c++不理解委托。然后我想我应该创建一个单独的objective-c类作为NSMenuDelegate,并将它的实例作为成员对象添加到我的c++类中。由于我能够将其他objective-c对象添加为成员,所以我认为这应该是可行的。但是,当我在c++类的头文件中包含新的objective-c类的头文件时,我从apple头文件(NSValue)中得到了数百个关于“在'@' token之前预期的不限定id”的错误。h,NSObject。很明显,这是行不通的,至少现在不行。当在类头文件中包含任何cocoa头时,我都会得到相同的结果。
I then thought I'd try a forward-declaration of the objective-c class (that is how I got the other objective-c objects working). however, this didn't work either- if I declare it as "class myClassName" I get an error about re-defining the class as a different type of symbol (presumably c++ class vs objective-c protocol). If I try to forward declare it as @protocol myClassName, I get an error about "expected unqualified-id before '@' token". So how can I make this work?
然后我想尝试一个objective-c类的前向声明(这就是我让其他objective-c对象工作的方式)。然而,这也不起作用——如果我将它声明为“myClassName”,我就会得到一个错误,即将类重新定义为不同类型的符号(假设是c++类vs objective-c协议)。如果我试图将其声明为@protocol classmyname,则会得到一个关于“在'@' token之前预期的不限定id”的错误。那么我该怎么做呢?
4 个解决方案
#1
10
Ok to answer your question:
好回答你的问题:
reportwindow.h is additionally included in a .cpp file, if that makes a difference.
reportwindow。h被另外包含在.cpp文件中,如果这有什么不同的话。
It does make a difference. Any compilation unit (cpp file in this case) that is touching Objective-C code has to be renamed to .mm or .m. Including the header that in turn is including Objective-C stuff in a C++ file will lead to the problem that the C++ compiler sees Objective-C code which it cannot handle.
这是有区别的。任何涉及Objective-C代码的编译单元(本例中为cpp文件)都必须重命名为.mm或.m。在c++文件中包含Objective-C内容的头会导致c++编译器看到它无法处理的Objective-C代码的问题。
Renaming the cpp file to mm will select the Objective-C option during compilation (which isn't when the file is named cpp or c) and hence allow to compile stuff with the Objective-C tokens (mainly "@" in your case).
将cpp文件重命名为mm将在编译过程中选择Objective-C选项(当文件命名为cpp或c时不是),因此允许使用Objective-C令牌(主要是“@”)编译内容。
An alternative would be not to include the Objective-C delegate class to your C++ class but rather include a pointer to your C++ class within the Objective-C delegate (i.e. implement it the other way around). This way you could arrange things such that the Objective-C code isn't touching the C++ code.
另一种方法是不将Objective-C的delegate类包含到c++类中,而是在Objective-C委托中包含一个指向c++类的指针(也就是说,将它反过来执行)。通过这种方式,您可以安排一些事情,使Objective-C代码不会触及c++代码。
Edit: Actually, I'd prefer the second suggestion. Here is an example:
编辑:事实上,我更喜欢第二个建议。这是一个例子:
DelegateClass.h:
DelegateClass.h:
class MyCPPClassHandlingStuff;
@interface MyDelegateObject : NSObject <SomeDelegateProtocol> {
MyCPPClassHandlingStuff *m_handlerInstance;
}
- (id) initWithCPPInstance:(MyCPPClassHandlingStuff*)cppInstance;
- (void) theDelegateProtocolMethod;
@end
DelegateClass.mm
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
And well the MyCPPClassHandlingStuff.h:
和MyCPPClassHandlingStuff.h:
#ifndef __MyCPPClassHandlingStuff_H__
#define __MyCPPClassHandlingStuff_H__
class MyCPPClassHandlingStuff
{
public:
MyCPPClassHandlingStuff();
void handleDelegateMethod();
};
#endif /* __MyCPPClassHandlingStuff_H__ */
MyCPPClassHandlingStuff can be initialized from Objective-C but you cannot initialise any Objective-C class from C++ code there. If you need to use Objective-C in your C++ code, you would have to compile it as Objective-C (i.e. use an .mm file). I leave the .cpp details as an exercise for the reader ;)
可以从Objective-C初始化mycppclasshandstuff,但是不能从c++代码初始化任何Objective-C类。如果您需要在c++代码中使用Objective-C,那么必须将其编译为Objective-C(即使用.mm文件)。我把。cpp细节留给读者作为练习;)
#2
0
I then thought I'd try a forward-declaration of the objective-c class (that is how I got the other objective-c objects working). however, this didn't work either- if I declare it as "class myClassName" I get an error about re-defining the class as a different type of symbol (presumably c++ class vs objective-c protocol).
然后我想尝试一个objective-c类的前向声明(这就是我让其他objective-c对象工作的方式)。然而,这也不起作用——如果我将它声明为“myClassName”,我就会得到一个错误,即将类重新定义为不同类型的符号(假设是c++类vs objective-c协议)。
Why not forward-declare it as @class myClassName
?
为什么不把它声明为@ myClassName呢?
#3
0
Make an Objective-C class to satisfy the delegate protocol, and have it delegate to your C++ class. The problem is that the AppKit expects to talk to Objective-C objects, so you need a shim to delegate to your C++ objects. (Yes you can do some runtime abuse, defining an isa pointer in your C++ class to make it somewhat compatible with ObjC objects (to the point where you can send messages to C++ classes), but don't do that. It's nasty.)
创建一个Objective-C类来满足委托协议,并将其委托给c++类。问题是AppKit期望与Objective-C对象对话,所以需要一个shim来委托给c++对象。(是的,您可以做一些运行时滥用,在您的c++类中定义一个isa指针,以使它与ObjC对象有一定的兼容性(可以向c++类发送消息),但是不要这样做。这是令人讨厌的。)
So make a shim which is initialized with your C++ class, has that as an ivar. It should implement the delegate methods you're interested in, and pass those along to your C++ class in a manner that it can understand. Tada, done.
因此,用c++类初始化一个shim,它是一个ivar。它应该实现您感兴趣的委托方法,并以它能够理解的方式将这些方法传递给您的c++类。恩,做的。
#4
0
There is some useful information on how to set up your headers so they can be used both from ObjC and C++ in Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?
有一些关于如何设置头文件的有用信息,可以在ObjC和c++中使用,我可以在编译和链接中将c++主函数和类从Objective-C和/或C例程中分离出来吗?
#1
10
Ok to answer your question:
好回答你的问题:
reportwindow.h is additionally included in a .cpp file, if that makes a difference.
reportwindow。h被另外包含在.cpp文件中,如果这有什么不同的话。
It does make a difference. Any compilation unit (cpp file in this case) that is touching Objective-C code has to be renamed to .mm or .m. Including the header that in turn is including Objective-C stuff in a C++ file will lead to the problem that the C++ compiler sees Objective-C code which it cannot handle.
这是有区别的。任何涉及Objective-C代码的编译单元(本例中为cpp文件)都必须重命名为.mm或.m。在c++文件中包含Objective-C内容的头会导致c++编译器看到它无法处理的Objective-C代码的问题。
Renaming the cpp file to mm will select the Objective-C option during compilation (which isn't when the file is named cpp or c) and hence allow to compile stuff with the Objective-C tokens (mainly "@" in your case).
将cpp文件重命名为mm将在编译过程中选择Objective-C选项(当文件命名为cpp或c时不是),因此允许使用Objective-C令牌(主要是“@”)编译内容。
An alternative would be not to include the Objective-C delegate class to your C++ class but rather include a pointer to your C++ class within the Objective-C delegate (i.e. implement it the other way around). This way you could arrange things such that the Objective-C code isn't touching the C++ code.
另一种方法是不将Objective-C的delegate类包含到c++类中,而是在Objective-C委托中包含一个指向c++类的指针(也就是说,将它反过来执行)。通过这种方式,您可以安排一些事情,使Objective-C代码不会触及c++代码。
Edit: Actually, I'd prefer the second suggestion. Here is an example:
编辑:事实上,我更喜欢第二个建议。这是一个例子:
DelegateClass.h:
DelegateClass.h:
class MyCPPClassHandlingStuff;
@interface MyDelegateObject : NSObject <SomeDelegateProtocol> {
MyCPPClassHandlingStuff *m_handlerInstance;
}
- (id) initWithCPPInstance:(MyCPPClassHandlingStuff*)cppInstance;
- (void) theDelegateProtocolMethod;
@end
DelegateClass.mm
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
And well the MyCPPClassHandlingStuff.h:
和MyCPPClassHandlingStuff.h:
#ifndef __MyCPPClassHandlingStuff_H__
#define __MyCPPClassHandlingStuff_H__
class MyCPPClassHandlingStuff
{
public:
MyCPPClassHandlingStuff();
void handleDelegateMethod();
};
#endif /* __MyCPPClassHandlingStuff_H__ */
MyCPPClassHandlingStuff can be initialized from Objective-C but you cannot initialise any Objective-C class from C++ code there. If you need to use Objective-C in your C++ code, you would have to compile it as Objective-C (i.e. use an .mm file). I leave the .cpp details as an exercise for the reader ;)
可以从Objective-C初始化mycppclasshandstuff,但是不能从c++代码初始化任何Objective-C类。如果您需要在c++代码中使用Objective-C,那么必须将其编译为Objective-C(即使用.mm文件)。我把。cpp细节留给读者作为练习;)
#2
0
I then thought I'd try a forward-declaration of the objective-c class (that is how I got the other objective-c objects working). however, this didn't work either- if I declare it as "class myClassName" I get an error about re-defining the class as a different type of symbol (presumably c++ class vs objective-c protocol).
然后我想尝试一个objective-c类的前向声明(这就是我让其他objective-c对象工作的方式)。然而,这也不起作用——如果我将它声明为“myClassName”,我就会得到一个错误,即将类重新定义为不同类型的符号(假设是c++类vs objective-c协议)。
Why not forward-declare it as @class myClassName
?
为什么不把它声明为@ myClassName呢?
#3
0
Make an Objective-C class to satisfy the delegate protocol, and have it delegate to your C++ class. The problem is that the AppKit expects to talk to Objective-C objects, so you need a shim to delegate to your C++ objects. (Yes you can do some runtime abuse, defining an isa pointer in your C++ class to make it somewhat compatible with ObjC objects (to the point where you can send messages to C++ classes), but don't do that. It's nasty.)
创建一个Objective-C类来满足委托协议,并将其委托给c++类。问题是AppKit期望与Objective-C对象对话,所以需要一个shim来委托给c++对象。(是的,您可以做一些运行时滥用,在您的c++类中定义一个isa指针,以使它与ObjC对象有一定的兼容性(可以向c++类发送消息),但是不要这样做。这是令人讨厌的。)
So make a shim which is initialized with your C++ class, has that as an ivar. It should implement the delegate methods you're interested in, and pass those along to your C++ class in a manner that it can understand. Tada, done.
因此,用c++类初始化一个shim,它是一个ivar。它应该实现您感兴趣的委托方法,并以它能够理解的方式将这些方法传递给您的c++类。恩,做的。
#4
0
There is some useful information on how to set up your headers so they can be used both from ObjC and C++ in Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?
有一些关于如何设置头文件的有用信息,可以在ObjC和c++中使用,我可以在编译和链接中将c++主函数和类从Objective-C和/或C例程中分离出来吗?