简体   繁体   English

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

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

Right now my OS X 10.9 project is set up with a GUI in Objective-C and all the processing in a C++ class. 现在,我的OS X 10.9项目在Objective-C中设置有GUI,并且所有处理都在C ++类中。 This doesn't seem like the best way, but this was given to me and I have to work with these constraints. 这似乎不是最好的方法,但这是给我的,我必须处理这些约束。 I currently have a NSSlider in the Cocoa GUI. 我目前在可可GUI中有一个NSSlider I want to be able to have this NSSlider control a variable x in the C++ class. 我希望能够让NSSlider在C ++类中控制变量x

Currently the tolerance bar is working when I run the program (working meaning it's continuously updating its value as per my sliding). 目前,当我运行程序时,公差栏正在工作(正常工作意味着它会根据我的滑动不断更新其值)。

Header for NSSlider ( Slider.h ): NSSlider标头( Slider.h ):

@interface Slider : NSObject {
@private
    __weak IBOutlet NSTextField *sliderValue;
    __weak IBOutlet NSSlider *slider;
}

- (IBAction)updateSliderValue:(id)sender;

@end

Implementation for the NSSlider ( Slider.mm ): NSSlider实现( Slider.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
}

Here is the relevant snippet from Main.h : 这是Main.h的相关代码段:

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

    private:
        int x;
};

How do I include CMain.h in the Objective-C++ (which, the .h file or .mm file? and how?) such that it would allow me to call the methods in CMain.h ? 如何在Objective-C++ (包括.h文件或.mm文件?如何?)中包含CMain.h ,以便可以调用CMain.h的方法? How would I phrase the method call in Objective-C to set x 's value using the setValueofX(sliderValue) ? 我该如何用setValueofX(sliderValue)在Objective-C中调用该方法来设置x的值?

Please let me know if more information is needed! 请让我知道是否需要更多信息! Any help or thoughts are appreciated! 任何帮助或想法表示赞赏!

Thanks! 谢谢!

The code for calling the setter is the same as it would be in C++. 调用设置器的代码与C ++中的代码相同。 However, you'd need a pointer to the CMain object to be able to call the method on it. 但是,您需要一个指向CMain对象的指针才能调用它上的方法。 I don't know where that object currently resides. 我不知道该对象当前位于何处。 If there is no object yet in another object, you probably want to create one, which you can by just declaring an instance variable CMain myCMain; 如果另一个对象中还没有对象,则可能要创建一个对象,只需声明一个实例变量CMain myCMain; and then calling myCMain.setValueOfX( [slider intValue] ); 然后调用myCMain.setValueOfX( [slider intValue] ); in updateSliderValue: . updateSliderValue:

As to where to include the C++ class, it's really your choice. 至于在哪里包括C ++类,这实际上是您的选择。 However, if you use any C++ in your header, it will take a bunch of careful extra work to include it from plain .m files. 但是,如果您在标头中使用任何C ++,则需要大量的额外工作才能将它们包含在纯.m文件中。 So in general I try to stick to plain C and ObjC in the header, and only use C++ in the .mm file. 因此,通常我会尝试在标头中使用普通C和ObjC,并且仅在.mm文件中使用C ++。 You can use a class extension (sometimes called "class continuation" as well) to declare additional ivars in your .mm file to keep them out of the header. 您可以使用类扩展名(有时也称为“类延续”)在.mm文件中声明其他ivars,以将其保留在标头之外。

If you want more info about ObjC++, I answered in detail on another post: Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link? 如果您想了解有关ObjC ++的更多信息,我在另一篇文章中详细回答了: 我可以在编译和链接时将C ++主要函数和类与Objective-C和/或C例程分开吗? and that also links to a Podcast I was a guest on where I talk about a lot of the details and tricks for integrating ObjC and C++. 这也链接到一个Podcast,我是一个嘉宾,在这里我谈论了许多集成ObjC和C ++的细节和技巧。

Aside: I hope these are not actual names and comments you're using. 除了:我希望这些不是您使用的实际名称和注释。 Never have an ObjC class without a prefix (3 letters, Apple stated they reserve all 2-letter prefixes for their own use, and they've used un-prefixed internal class names in the past which broke some peoples' programs). 永远不要有没有前缀的ObjC类(3个字母,Apple表示他们保留所有2个字母的前缀供自己使用,并且过去使用的是不带前缀的内部类名称,这破坏了某些人的程序)。 Also, "Slider" is a bad name, as NSSlider is the actual slider, and this sounds like it should be a subclass. 另外,“ Slider”是一个坏名字,因为NSSlider是实际的滑块,听起来像它应该是子类。 You really want to call this an ISTSliderController or whatever. 您真的想将其称为ISTSliderController或其他名称。

I found a solution by noting that there was an existing wrapper class CWrapper.h and it was an objective-C++ implementation class CWrapper.mm . 我发现一个解决方案是注意到存在一个包装类CWrapper.h ,它是一个目标C ++实现类CWrapper.mm There was a CMain variable instantiated as cmain . 有一个CMain变量实例化为cmain I made a getter method for x and I simply created a static method in the wrapper class + (void) passX:(int) number; 我为x创建了一个getter方法,然后在包装类+ (void) passX:(int) number;创建了一个静态方法+ (void) passX:(int) number; that I called in the slider class. 我在滑块类中调用过的。 I chose a static method because this for this application, this value will never have to be different between objects. 我选择了静态方法,因为对于该应用程序,此值在对象之间永远不必相同。 I hope I made the right choice here! 希望我在这里做出了正确的选择!

See code changes below : 请参阅下面的代码更改

I added this to the Slider.h file. 我将此添加到Slider.h文件中。

- (int)X;

I added the getter and [CWrapper passX:[self getX]]; 我添加了吸气剂和[CWrapper passX:[self getX]]; to the updateSliderValue method in the Slider.mm file. 到Slider.mm文件中的updateSliderValue方法。

- (int)X {
    return [slider intValue];
}

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

This is the code I added to CWrapper.h. 这是我添加到CWrapper.h中的代码。

+ (void) passX:(int) number;

This is the code I added to CWrapper.mm. 这是我添加到CWrapper.mm的代码。

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

Here's an all objective-c and objective-c++ answer: 这是所有Objective-C和Objective-C ++的答案:

CMain.h: CMain.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: 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

and if you want to use C-style functions then: 如果要使用C样式的函数,则:

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

And this works because a C++ class function in C is the same as: 之所以可行,是因为C中的C ++类函数与以下相同:

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

Both are the exact same thing. 两者是完全一样的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM