2014-10-28 1 views
0

지금 내 OS X 10.9 프로젝트는 Objective-C에서 GUI로 설정되고 C++ 클래스에서 모든 처리가 설정됩니다. 이것은 최선의 방법처럼 보이지 않지만 이것이 나에게 주어졌고 나는 이러한 제약들로 작업해야만한다. 현재 코코아 GUI에 NSSlider이 있습니다. 나는이 NSSlider이 C++ 클래스의 변수 x을 제어하도록하고 싶습니다.Objective-C에서 C++ 메서드를 호출하는 방법 Objective-C++을 사용하여 Cocoa 인터페이스

현재 허용 오차 막대는 프로그램을 실행할 때 작동합니다 (작동 중일 때 계속 슬라이딩 할 때마다 값이 계속 업데이트됩니다).

헤더 NSSlider (Slider.h)의 경우 : NSSlider (Slider.mm)에 대한

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

- (IBAction)updateSliderValue:(id)sender; 

@end 

구현 : 어떻게

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

    private: 
     int x; 
}; 

: 여기

#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에서 관련 조각입니다나는 Objective-C++CMain.h을 포함합니다 ( .h 파일 또는 .mm 파일입니까? 그리고 어떻게?) 내가 그 방법을 호출 할 수 있도록 그런 것 CMain.h? Objective-C에서 setValueofX(sliderValue)을 사용하여 x의 값을 설정하는 방법은 무엇입니까?

자세한 정보가 필요하면 알려주세요. 어떤 도움이나 생각을 부탁드립니다!

감사합니다.

답변

1

기존 래퍼 클래스 CWrapper.h이 있었고 objective-C++ 구현 클래스 CWrapper.mm이라는 것을 발견하여 해결책을 찾았습니다. CMain 변수가 cmain으로 인스턴스화되었습니다. x에 대한 getter 메서드를 만들었고 간단히 슬라이더 클래스에서 호출 한 래퍼 클래스 + (void) passX:(int) number;에 정적 메서드를 만들었습니다. 이 응용 프로그램의 경우이 값은 객체간에 다를 필요가 없기 때문에 정적 메서드를 선택했습니다. 내가 올바른 선택을했으면 좋겠어! 다음

참조 코드 변경 :

은 내가 Slider.h 파일이 추가되었습니다.
- (int)X; 

은 내가 Slider.mm 파일의 updateSliderValue 방법에 getter와 [CWrapper passX:[self getX]];을 추가했다.

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

한가지주의 사항 : "get"을 사용하여 Objective-C에서 getter의 이름을 시작하지 마십시오. 이는 매개 변수에 부작용을주는 메소드에 예약되어 있습니다. 그냥 공차라고 부르세요. 그런 식으로 KVO 나 그러한 명명 표준을 준수하는 다른 메커니즘을 사용할 수 있습니다. – uliwitness

+0

@uliwitness 팁 주셔서 감사! –

3

setter를 호출하는 코드는 C++에서와 동일합니다. 그러나 메서드를 호출 할 수 있도록 CMain 개체에 대한 포인터가 필요합니다. 나는 그 물건이 현재 어디에 있는지 모른다. 다른 객체에 아직 객체가 없으면 인스턴스 변수를 CMain myCMain;으로 선언 한 다음 myCMain.setValueOfX([slider intValue]);updateSliderValue:으로 호출하면됩니다.

C++ 클래스를 포함 할 위치는 실제로 선택 사항입니다. 그러나 헤더에서 C++을 사용하는 경우 일반 .m 파일에서 추가하는 작업이 많이 필요합니다. 그래서 일반적으로 헤더의 일반 C와 ObjC를 고수하고 .mm 파일에서 C++ 만 사용하려고합니다. 클래스 확장 (때때로 "클래스 계속"이라고도 함)을 사용하여 .mm 파일에서 추가 ivars를 선언하여 머리말을 벗어나지 않게 할 수 있습니다.

ObjC++에 대한 자세한 정보가 필요하면 다른 게시물에 대한 자세한 내용은 Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?이며 그 또한 Podcast에 대한 링크입니다. ObjC와 C++를 통합하는 데 필요한 세부 정보와 트릭에 대해 많이 이야기합니다.

기타 : 사용중인 실제 이름과 설명이 아닌 것이 좋겠습니다. 접두사가없는 ObjC 클래스는 절대로 사용하지 마십시오 (Apple은 3 글자로 자신의 사용을 위해 2 글자 접두어를 모두 보유하고 있으며 일부 접두어를 사용하지 않은 접두사가없는 내부 클래스 이름을 사용했습니다). 또한 NSSlider가 실제 슬라이더이기 때문에 "Slider"는 나쁜 이름입니다.이 슬라이더는 하위 클래스 인 것처럼 들립니다. 정말 이것을 ISTSliderController 또는 무엇이든 호출하려고합니다.

+0

/@ uliwitness 제안 해 주셔서 감사합니다. 저는 그들이하고있는 것에 전문화되어있는 것처럼 변수 이름을 변경했습니다. 나는 이것을 이렇게 소개하는 것이 더 합리적 이길 바랬습니다. 그래서'CMain' 객체는 다른 클래스, 즉 역설적으로'CWrapper.mm'라고하는 래퍼 클래스에서 인스턴스화됩니다. 이 변수의 또 다른 인스턴스를 만들고 싶지 않습니다. 어떻게이 변수를 가리킬 수 있습니까? 다른 방법으로는 set 메소드를 정적 메소드 (인스턴스 불가지론 자 (생각하니?))로 만들고 다른 객체간에 값을 동일하게 유지하는 방법을 고려하고 있습니다. 그것을 동일하게하면 내 응용 프로그램에서 작동합니다. –

+1

디자인이 더 쉬워 보이기 때문에 정적으로 만들지 마십시오. 결국 나중에이 유형의 객체가 두 개 필요하다면 뒤에서 만 물을 것입니다. 실제로 C++은 Objective-C와 다르지 않습니다. 이 두 객체에 대해 알고있는 객체를 찾고, 다른 객체가 가지고있는'CMain'의 인스턴스에 대한 포인터 인'ISTSliderController'를 넘겨 주면됩니다. 일반적으로 루트에 가까운 오브젝트가 오브젝트의 아래에 오브젝트를 작성하는 오브젝트의 계층 구조가 있습니다. 그 시점에서 당신은 보통 그런 연결을 연결합니다. – uliwitness

-2

다음은 모두 objective-C 및 objective-C++ 대답입니다.

CMain입니다.시간 :

#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); 

둘 다 동일합니다 맡은 일.

+0

Objective-C++은이 방법보다 더 나은 선택입니다. ObjC++는 ObjC 코드에서 C++ 문을 사용할 수 있음을 의미합니다. 위의 코드는 코드를 읽기 쉽지 않게 만들고 ABI의 세부 정보에 의존한다고 생각합니다. – uliwitness

+0

실제로 Objective-C에서 Objective-C++ 코드를 사용할 수 있다고 생각하십니까? 농담이야. 당신이'std :: cout'으로 그것을 보자. 그는 무엇이든간에 래퍼를 써야한다. 그의 헤더는 전적으로 C 또는 Objective-C 여야합니다. Objective-C++에서 아무 것도 없습니다.Objective-C++는 Objective-C에서 C++을 전혀 사용할 수 없다는 것을 의미하지는 않습니다. 여전히 C 스타일의 코드로 C++ 코드를 래핑하고 있습니다. 상황에 따라 Objective-C++를 사용하는 것이 더 쉽습니다. Objective-C에서 Objective-C++ 코드를 사용하는 것은'extern "C"'를 사용하는 것과 동의어입니다. – Brandon

+2

저는 약 10 년 동안 커다란 혼합 C++/ObjC 프로젝트를 작업 해 왔습니다. 그리고 OP는 ObjC에서 C++ 사용에 관해 묻지 않았습니다. OP는 ObjC++ (.mm) 파일에서 C++ 사용에 관해 질문했습니다. (더 많은 정보는 내 대답을 참조하십시오) – uliwitness

관련 문제