Objective-C 대신 Cocoa와 함께 C ++를 사용 하시겠습니까?


122

Apple이 Carbon 64 비트를 지원하지 않기 때문에 C ++ 및 Cocoa 프레임 워크를 사용하는 애플리케이션을 작성하고 싶습니다. C ++는 Linux 및 Windows에서 구현할 때 매우 바닐라 보이지만 Mac OS X에서는 추가 Apple 특정 코드 조각이 필요한 것 같습니다 (Obj-C 래퍼와 같은). 내가 틀릴 수도 있지만, 애플이 개발자들에게 C ++가 아닌 Objective-C로 작성하도록 강요하는 것 같다.

크로스 플랫폼을 유지하기 쉬운 Mac에서 코드를 작성하는 경로를 찾으려고합니다. Linux / Windows 용 C ++로 코드를 작성한 다음 Objective-C에서 많은 부분을 다시 작성하는 것은 매우 비효율적입니다.

향후 지원되고 Xcode에서 지원 될 C ++로 코드를 작성하는 방법이 있습니까? 또한 이것이 가능하다면 Xcode에서 C ++와 Objective-C를 어떻게 혼합합니까? 감사.

답변:


110

Cocoa 애플리케이션을 완전히 C ++로 작성할 수는 없습니다. Cocoa는 Key-Value Bindings, delegates (Cocoa 스타일), target-action 패턴과 같은 많은 핵심 기술에 Objective-C의 후기 바인딩 기능에 크게 의존합니다. 후기 바인딩 요구 사항은 C ++ ⁱ과 같은 컴파일 타임 바인딩 된 유형 언어로 Cocoa API를 구현하는 것을 매우 어렵게 만듭니다. 물론 OS X에서 실행되는 순수한 C ++ 앱을 작성할 수 있습니다. 단지 Cocoa API를 사용할 수 없습니다.

따라서 다른 플랫폼의 C ++ 앱과 Cocoa 기반 애플리케이션간에 코드를 공유하려는 경우 두 가지 옵션이 있습니다. 첫 번째는 C ++로 모델 레이어를 작성하고 Cocoa로 GUI를 작성하는 것입니다. 이것은 Mathematica를 포함한 일부 대규모 앱에서 사용되는 일반적인 접근 방식 입니다. C ++ 코드는 변경하지 않고 그대로 둘 수 있습니다 (OS X에서 C ++를 작성하거나 컴파일하기 위해 "펑키"애플 확장이 필요하지 않음). 컨트롤러 계층은 Objective-C ++ (사용자가 참조하는 "펑키"Apple 확장)을 사용합니다. Objective-C ++는 Objective-C가 C의 상위 집합 인 것처럼 C ++의 상위 집합입니다. Objective-C ++에서는 [some-objc-object callMethod];C ++ 함수 내에서 objc 스타일 메시지 전달 호출 (예 :)을 만들 수 있습니다 . 반대로 ObjC 코드 내에서 다음과 같이 C ++ 함수를 호출 할 수 있습니다.

@interface MyClass {
    MyCPPClass *cppInstance;
}
@end

@implementation MyClass
- (id)init {
    if(self = [super init]) {
        cppInstance = new MyCPPClass();
    }
    return self;
}
- (void) dealloc {
    if(cppInstance != NULL) delete cppInstance;
    [super dealloc];
}
- (void)callCpp {
    cppInstance->SomeMethod();
}
@end

Objective-C 언어 가이드 에서 Objective-C ++에 대해 자세히 알아볼 수 있습니다 . 그러면 뷰 레이어는 순수 Objective-C가 될 수 있습니다.

두 번째 옵션은 크로스 플랫폼 C ++ 툴킷을 사용하는 것입니다. Qt는툴킷이 청구서에 맞을 수 있습니다. 크로스 플랫폼 툴킷은 일반적으로 Mac 사용자가 모든 룩앤필 세부 정보를 정확하게 얻지 못하고 Mac 사용자는 Mac 응용 프로그램의 UI에서 세련미를 기대하기 때문에 경멸합니다. Qt는 놀랍게도 좋은 일을하고 있으며, 청중과 앱 사용에 따라 충분할 수 있습니다. 또한 Qt API에 대략적인 대체 항목이 있지만 Core Animation 및 일부 QuickTime 기능과 같은 일부 OS X 관련 기술을 잃게됩니다. 지적했듯이 Carbon은 64 비트로 이식되지 않습니다. Qt가 Carbon API에 구현 되었기 때문에 Trolltech / Nokia는 Qt를 Cocoa API로 포팅해야 64 비트 호환이 가능합니다. 내 이해는 Qt의 다음 릴리스 (현재 릴리스 후보)은이 전환을 완료하고 OS X에서 64 비트와 호환됩니다. C ++ 및 Cocoa API 통합에 관심이 있다면 Qt 4.5의 소스를 살펴볼 수 있습니다.


ⁱ 잠시 동안 Apple은 Cocoa API를 Java에서 사용할 수 있도록 만들었지 만 브리지에는 광범위한 수동 조정이 필요했고 위에서 설명한 키-값 바인딩과 같은 고급 기술을 처리 할 수 ​​없었습니다. 현재 Python, Ruby 등과 같은 동적 형식의 런타임 바인딩 언어는 Objective-C없이 Cocoa 앱을 작성하기위한 유일한 실제 옵션입니다 (물론 이러한 브리지는 내부적으로 Objective-C를 사용합니다).


나는 현재 작은 Ogre3D 응용 프로그램을 이식하려고 시도하고 있는데 매우 고통스러워 보입니다. Apple이 모든 사람을 Objc로 변환하려고합니까, 아니면 이것이 정말 기능입니까?
jokoon

68

어리석게 들릴지 모르지만 실제로는 순수 C ++ 코드를 작성하여 Mac OS X 용 GUI를 만들 수 있지만 Cocoa 프레임 워크와 연결해야합니다.

/*
 * test1.cpp
 * This program shows how to access Cocoa GUI from pure C/C++
 * and build a truly functional GUI application (although very simple).
 * 
 * Compile using:
 *   g++ -framework Cocoa -o test1 test1.cpp
 *
 * that will output 'test1' binary.
 */


#include <CoreFoundation/CoreFoundation.h>
#include <objc/objc.h>
#include <objc/objc-runtime.h>
#include <iostream>

extern "C" int NSRunAlertPanel(CFStringRef strTitle, CFStringRef strMsg,
                               CFStringRef strButton1, CFStringRef strButton2, 
                               CFStringRef strButton3, ...);


int main(int argc, char** argv)
{
    id app = NULL;
    id pool = (id)objc_getClass("NSAutoreleasePool");
    if (!pool)
    {
        std::cerr << "Unable to get NSAutoreleasePool!\nAborting\n";
        return -1;
    }
    pool = objc_msgSend(pool, sel_registerName("alloc"));
    if (!pool)
    {
        std::cerr << "Unable to create NSAutoreleasePool...\nAborting...\n";
        return -1;
    }
    pool = objc_msgSend(pool, sel_registerName("init"));

    app = objc_msgSend((id)objc_getClass("NSApplication"),
                       sel_registerName("sharedApplication"));

    NSRunAlertPanel(CFSTR("Testing"),
                    CFSTR("This is a simple test to display NSAlertPanel."),
                    CFSTR("OK"), NULL, NULL);

    objc_msgSend(pool, sel_registerName("release"));
    return 0;
}

17
이것은 훌륭합니다. 더 복잡한 예제가 있습니까? 예를 들어, NSWindow를 여는가?
imallett

test1.cpp : 'int main (int, char **)'함수에서 : test1.cpp : 26 : 48 : 오류 : 초기화 ID에서 'Class {aka objc_class *}'를 'id {aka objc_object *}'로 변환 할 수 없습니다. pool = objc_getClass ( "NSAutoreleasePool"); ^ test1.cpp : 41 : 61 : 오류 : 인수 '1'에 대해 'Class {aka objc_class *}'를 'id {aka objc_object *}'로 변환 할 수 없습니다. 'objc_object * objc_msgSend (id, SEL, ...)' sel_registerName ( "sharedApplication")); ^
Jichao 2014 년

6
연타와 호환성을 참조 @Jichao 내부 오브젝티브 C 타입 - 수정이 간단 교체 objc_getClass(id)objc_getClass
드미트리 Isaev

예를 들어 std :: string을 사용하여 어떻게 설정할 수 있습니까? 경고 패널의 제목? 나는 c_str ()을 사용해 보았지만 아무것도 작동하지 않았습니다 ...
mdre

1
이것은 macOS Catalina에서 더 이상 컴파일되지 않습니다
JC Rocamonde

18

예, C ++ 만 사용할 수 있습니다 (예 : * .cpp 파일로 작성). C ++ 및 Objective-C를 * .mm 파일 내에서 혼합 할 수도 있습니다 (표준 Objective-C 코드는 * .m 파일에 저장 됨).

물론 사용자 인터페이스에 Objective-C를 사용하고 C ++ 개체에 대한 Objective-C 래퍼를 만들어야합니다. 또 다른 옵션은 Windows, Mac OS X 및 Linux를 지원하는 C ++ 프레임 워크 인 Qt 로 전환하는 것이며 차기 버전 4.5와 함께 LGPL에 따라 출시 될 예정입니다.


23
Qt를 사용하면 앱이 짜증납니다. Qt 기반 앱은 기본 Mac 앱처럼 보이고 느껴지지 않습니다. (예를 들어 Google 어스를 참조하십시오.)
Peter Hosey

15
Peter : 전혀 사실이 아닙니다. Qt 기반 앱은 기본 Mac 앱과 모양과 느낌이 동일 할 수 있습니다. 각 플랫폼에서 기본 GUI를 작성하는 것보다 훨씬 쉬운 플랫폼 별 조정 만 수행하면됩니다.
Mike McQuaid

12
마이크, 당신은 잘못 알고 있습니다. 다른 단점 중에서도 Mac의 Qt 기반 앱은 기본 컨트롤을 전혀 사용하지 않으며 Qt 라이브러리가 모든 드로잉 자체를 수행합니다. 즉, Qt 앱은 2D 렌더링을위한 하드웨어 가속을 얻지 못하고 Apple이 표준 컨트롤에 적용한 UI 변경 사항과 동기화되지 않으며 Qt 앱은이를 재발 명하지 않는 한 ADA 규정 준수 또는 스크립팅 가능성을 제공 할 수 없습니다. 스스로 바퀴. 즉, Mac에서 Qt 앱을 제공하려고 시도하지 마십시오. 구글은 그것을 피할 수 있습니다. 당신은 할 수 없습니다.
NSResponder

13
그들은 네이티브 컨트롤을 사용하므로 Qt에 Cocoa 및 Carbon 버전이 있습니다. 다른 문제가 있지만 많은 사람들이 Mac에서 Qt 응용 프로그램을 제공하고 잘 작동합니다 (그리고 약간의 조정으로 완벽하게 작동합니다).
Mike McQuaid 2011 년

2
네이티브 컨트롤을 사용한다고해서 네이티브 앱처럼 보이고 느껴지는 것은 아닙니다 . 네이티브 느낌을 만드는 것은 각 OS의 차이 입니다. 특정 플랫폼에서 느껴지도록 앱을 조정하면 다른 플랫폼에서 네이티브로 느껴지지 않습니다. 그리고 일단 추상화 된 레이어에서 작은 동작을 미세 조정하는 것은 기본 레이어에서 수행하는 것보다 항상 어렵습니다.
eonil

9

예, 혼합 할 수 있습니다.

Objective-C를 사용하여 GUI 개체에서 직접 작동하고 알림을 받아야합니다.

이러한 Objective-C 개체는 순수한 Objective-C .m 파일 대신 .mm 파일에 넣으면 C ++ 논리를 직접 호출 할 수 있습니다. Objective-C ++를 나타 내기 위해 대문자 .M 사용을 제안하는 (많은) 오래된 조언을 볼 수 있지만 이것은 매우 불안정하고 컴파일러뿐만 아니라 사용자를 혼동 할 가능성이 있습니다.

각각의 모든 C ++ 개체를 래핑 할 필요는 없지만 Objective-C 코드에는 개체에 대한 포인터가 포함되어야합니다.

Apple은 더 이상이를 수행하는 방법을 보여주는 샘플을 게시하지 않습니다.

Realm [Objective] C ++ 에서 호스팅하는 Peter Steinberger의 멋진 비디오가 있습니다 . 무엇이 잘못 될 수 있습니까? 아직 Objective-C ++를 사용하는 모든 사람에게 적극 권장하며 스크립트를 빠르게 훑어 볼 수 있습니다.


귀하의 링크가 너무 고장 @SteveS
fferri

@fferi-위의 Steinberger 링크가 수정되었습니다. Carbon Cocoa Integration은 developer.apple.com에서 2007 년에 출시되었으며 Apple은이를 제거했습니다. 이것은 Carbon API를 사용하여 새로운 코드를 작성해서는 안된다는 것을 나타냅니다. 이 시점에서 Carbon을 사용하여 기존 코드를 유지하는 것조차 위험합니다. 이 질문에, 또는에 대한 허용 대답을 참조하십시오 이 하나의 당신이 C는 ++ / 오브젝티브 C 혼합해야하는 경우,하지만 당신은 탄소를 사용하지 않아야합니다. 즉, 여기 : Carbon-Cocoa-Integration
SteveS 2018-08-24

4

평범한 바닐라 C ++를 사용하려는 경우 절대적으로 지원되며 다른 플랫폼과 다르지 않습니다. Xcode에는 File> New Project> Command Line Utility> C ++ Tool에 템플릿이 있습니다. 또한 많은 인기있는 오픈 소스 라이브러리 (libcurl, libxml2, sqlite 등)가 OS X와 ​​함께 제공되며 동적 연결에 사용할 수 있습니다. 원치 않는 경우 Cocoa 또는 Apple 특정 제품을 사용할 필요가 없습니다.

앱의 특정 부분에서 Cocoa를 사용하고 싶다면 Objective-C ++를 살펴보세요 . 확장자를 .mm로 지정하거나 Xcode에서 파일을 마우스 오른쪽 버튼으로 클릭하고 정보 가져 오기> 일반을 선택한 다음 파일 유형을 sourcecode.cpp.objcpp로 변경하여 동일한 파일에서 C ++ 및 Objective-C를 혼합 할 수 있습니다. 두 번째 옵션은 Mac 관련 #ifdef 내에서 Objective-C를 사용하려는 .cpp 파일이있는 경우 유용합니다.


1
BTW, (정말 유용한) C ++ 템플릿은 최신 버전의 Xcode (4.x 및 5.x)와 함께 사라졌습니다
Jay

1

이것은 오래된 질문이지만 ...

나는 한 일부 코코아 클래스의 C ++ 래퍼를 만들기 위해 노력했다 .

꽤 좋은 경험이었습니다. C ++는 Objective-C보다 더 나은 형식 안전성을 제공하여 코드 작성을 줄였습니다. 그러나 컴파일 시간과 메모리 안전성은 더 나쁩니다. 가능하지만 일부 동적 기반 기능은 다루기가 쉽지 않았습니다. C ++에서 처리하는 것은 말이되지 않는다고 생각합니다.

어쨌든 내 프로젝트는 Swift의 발표로 인해 결국 포기되었습니다. 처음에 C ++를 사용하고 싶었던 모든 이유를 해결했으며 더 많은 것을 제공합니다.


0

순전히 그래픽 애플리케이션을 작성하는 경우, 즉 코드를 사용하여 모든 것을 그리는 경우 openFrameworks를 고려하십시오 . C / C ++ 위에 구축 된 오픈 소스 그래픽 프로그래밍 언어입니다. 그것은이 애드온 사람들이 언어를 확장 할 수 있습니다. 그들은 아이폰에 대한 애드온이 있습니다. iPhone 및 iPod touch 용 앱을 컴파일하는 데 도움이되는 라이브러리 및 XCode 프로젝트가 함께 제공된다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.