如何使用Objective-C++从Objective-CCocoa接口调用C++方法

How to call C++ method from Objective-C Cocoa Interface using Objective-C++

本文关键字:调用 C++ 方法 接口 Objective-CCocoa 何使用 Objective-C++      更新时间:2023-10-16

现在我的OSX10.9项目已经在Objective-C中设置了一个GUI,所有处理都在C++类中。这似乎不是最好的方式,但这是给我的,我必须克服这些限制。我目前在Cocoa GUI中有一个NSSlider。我希望能够让这个NSSlider控制C++类中的变量x

目前,当我运行程序时,公差条正在工作(工作意味着它会根据我的滑动不断更新其值)。

NSSliderSlider.h)的标题:

@interface Slider : NSObject {
@private
    __weak IBOutlet NSTextField *sliderValue;
    __weak IBOutlet NSSlider *slider;
}
- (IBAction)updateSliderValue:(id)sender;
@end

NSSliderSlider.mm)的实现:

#import "Slider.h"      // The NSSlider object
#import "CMain.h"       // The C++ class that does all the processing (not sure if this is the way to include a C++ interface in an Objective-C++ class or if this will allow me to call its methods)
@implementation Slider
-(void) awakeFromNib {
    [slider setIntValue:40];
    [sliderValue setIntValue:[slider intValue]];
}
- (IBAction)updateSliderValue:(id)sender {
    [sliderValue setIntValue:[slider intValue]];
    // Here is where I'd think that if I have a setValueofX(int number) method in the C++ class
    // I could call this somehow using objective-C++. I don't know if I can or how to call this method here
}

以下是Main.h:中的相关片段

class CMain(){
    public:
        CMain();
        void setValueofX(int number);
        int getValueofX();
    private:
        int x;
};

如何将CMain.h包含在Objective-C++中(.h文件或.mm文件是哪个?如何?),以便调用CMain.h中的方法?我该如何表述Objective-C中的方法调用以使用setValueofX(sliderValue)设置x的值?

如果需要更多信息,请告诉我!感谢您的帮助或想法!

谢谢!

调用setter的代码与C++中的代码相同。但是,您需要一个指向CMain对象的指针才能调用它上的方法。我不知道该对象当前所在的位置。如果另一个对象中还没有对象,那么您可能想要创建一个对象,只需声明一个实例变量CMain myCMain;,然后在updateSliderValue:中调用myCMain.setValueOfX( [slider intValue] );即可。

至于在哪里包含C++类,这确实是您的选择。然而,如果您在头中使用任何C++,那么从普通.m文件中包含它将需要大量额外的工作。因此,一般情况下,我会在头中使用纯C和ObjC,而在.mm文件中只使用C++。您可以使用类扩展名(有时也称为"类延续")在.mm文件中声明额外的ivar,以将它们排除在标头之外。

如果你想了解更多关于ObjC++的信息,我在另一篇文章中详细回答了:我可以在编译和链接时将C++主函数和类从Objective-C和/或C例程中分离出来吗?这也链接到我作为嘉宾的一个播客,在那里我谈论了许多集成ObjC和C++的细节和技巧。

旁白:我希望这些不是你实际使用的名字和评论。从来没有一个ObjC类没有前缀(3个字母,苹果表示他们保留所有2个字母的前缀供自己使用,而且他们过去使用过无前缀的内部类名,这破坏了一些人的程序)。此外,"Slider"是一个坏名字,因为NSSlider是实际的滑块,听起来它应该是一个子类。您真的想称之为ISTSliderController或其他什么。

我发现了一个解决方案,注意到有一个现有的包装类CWrapper.h,它是一个objective-C++实现类CWrapper.mm。有一个CMain变量实例化为cmain。我为x制作了一个getter方法,并简单地在封装器类+ (void) passX:(int) number;中创建了一个静态方法,我在滑块类中调用了该方法。我选择了一个静态方法,因为对于这个应用程序,这个值在对象之间永远不必不同。我希望我在这里做出了正确的选择!

请参阅下面的代码更改

我将其添加到Slider.h文件中。

- (int)X;

我将getter和[CWrapper passX:[self getX]];添加到Slider.mm文件中的updateSliderValue方法中。

- (int)X {
    return [slider intValue];
}
- (IBAction)updateSliderValue:(id)sender {
    [sliderValue setIntValue:[slider intValue]];
    [CWrapper passX:[self getX]];
}

这是我添加到CWrapper.h.的代码

+ (void) passX:(int) number;

这是我添加到CWrapper.mm.的代码

+ (void) passX:(int)num
{
    cmain.setValueofX(num);
}

这里有一个所有objective-c和objective-c++的答案:

C主要h:

#ifndef Testing_CMain_h
#define Testing_CMain_h
@interface CCMain : NSObject
-(CCMain*) init;
-(void) dealloc;
-(void)setValueofX:(int)number;
-(int)getValueofX;
@end
#endif

CMain.mm:

#import <Foundation/Foundation.h>
#import "CMain.h"
class CMain {
private:
    int x;
public:
    CMain() : x(0) {}
    void setValueofX(int number) {x = number;}
    int getValueofX() const {return x;}
};

@interface CCMain ()
@property (nonatomic, assign) CMain* inst;
@end
@implementation CCMain
-(CCMain*) init
{
    if (!_inst)
    {
        _inst = new CMain();
    }
    return self;
}
-(void) dealloc
{
    delete _inst;
    _inst = nil;
}
-(void)setValueofX:(int)number
{
    _inst->setValueofX(number);
}
-(int)getValueofX
{
    return _inst->getValueofX();
}
@end

如果你想使用C风格的函数,那么:

setValueofX(cmain_instance, value);
int val = getValueofX(cmain_instance);

这是因为C中的C++类函数与相同

void CMain::MyFunc(int X);
//vs..
void MyFunc(CMain* inst, int X);

两者完全相同。