Swift와 C ++를 함께 사용할 수 있습니까? Objective-C .mm 파일처럼


131

방금 .m 파일을 .mm로 변경하고 C ++을 사용했습니다. Swift와 동일한 작업을 수행하는 방법이 있습니까?

답변:


111

아니요. .m에서 .mm로 전환하면 실제로 Objective-C에서 Objective-C ++라는 다른 언어 (많은 미묘한 차이가 있음)로 전환됩니다. 따라서 실제로 C ++을 사용하지 않습니다. 대부분의 C ++를 입력으로 받아들이는 Objective-C ++를 사용하고 있습니다 (C ++가 대부분의 C를 입력으로 받아들이는 것과 같은 방식으로). 내가 C ++이 아니라고 말할 때 이름이 지정된 변수가 포함 된 C ++ 파일을 고려하십시오.nil (법적 C ++ 인) 다음 Objective-C ++로 컴파일하십시오.

스위프트는 같은 관계가 없습니다. C 또는 C ++의 수퍼 세트가 아니며, 다음 중 하나에서 직접 사용할 수 없습니다..swift 파일 .

"Cocoa 및 Objective-C와 함께 Swift 사용" 도 알려줍니다.

C ++ 코드를 Swift로 직접 가져올 수 없습니다. 대신 C ++ 코드 용 Objective-C 또는 C 랩퍼를 작성하십시오.


93
C / C ++ 코드베이스를 통합 한 Cocoa 앱을 사용하는 우리 모두는 이제 3 개 언어로 작성된 프로젝트를 유지해야합니다 .
Jay

6
Objective-c ++는 다른 언어는 아니지만 c ++와 Objective-c의 차이점은 미묘하지만 여전히 존재합니다.
amar

1
"nil"은 어떻게 합법적 인 C ++입니까? 그런 것은 없습니다 (적어도 표준 c ++에서는) 또 다른 예를 들어주십시오
rewolf

3
그러나 ObjC를 사용하면 .mm파일을 이동 하고 (거의) 완료 할 수 있습니다. 스위프트에서는 그렇지 않습니다.
chakrit

6
@rewolf, 나는 그가 다음 nil과 같은 변수를 의미한다고 생각합니다.int nil
Luke

165

혼란은 단지에서 파일 확장자 변화는 가정에서 올 수 .m하려면 .mm당신이, 현실에서, 그것은 그런 종류의 아무것도하지 않을 때, 언어를 해소하는 데 필요한 모든 것입니다. 그것은 아닙니다 .mm와 마찰을 유발하는 .cpp가이다, .h긍정적 안됩니다 헤더 C++헤더입니다.


같은 프로젝트 : 예.

에서 같은 프로젝트, 당신이 행복하게 혼합 할 수 있습니다 C , C ++를 , 목표 - C , 오브젝티브 C ++ , 스위프트 , 심지어 조립 .

  1. ...Bridging-Header.h: C , Objective-CObjective-C ++Swift에 노출시킵니다. 이 브리지를 사용하여
  2. <ProductModuleName>-Swift.h: 노출 자동으로 당신의 스위프트 표시 클래스 @objc목표 - C를
  3. .h: 그들은 모호의 모든 맛을 위해 사용되기 때문에 이것은 까다로운 부분입니다 C , ++ 여부, 목적 여부. A는 때 .h하나의 포함하지 않는 C ++를 키워드 같은 class, 그것은에 추가 할 수 있습니다 ...Bridging-Header.h, 그리고 해당 기능 어떤 노출 것 .c 또는 .cpp 그것을 선언하는 기능. 그렇지 않으면 해당 헤더는 순수한 C 또는 Objective-C API 로 랩핑되어야합니다 .

동일한 파일 : 아니요.

에서 같은 파일, 같은 모든 5. 혼합 할 수 없습니다 소스 파일 :

  1. .swift: 당신 스위프트 와 아무것도 섞을 수 없습니다
  2. .m: Objective-CC를 혼합 할 수 있습니다 . ( @Vinzzz )
  3. .mm: Objective-CC ++를 혼합 할 수 있습니다 . 이 브릿지는 Objective-C ++ 입니다. ( @Vinzzz ).
  4. .c: 순수한 C
  5. .cpp: 당신은 C ++ & Assembly ( @Vality )를 혼합 할 수 있습니다
  6. .h: 유비쿼터스와 모호한 C는 , C ++ , 오브젝티브 C 또는 목표 - C ++는 대답은, 그래서 그것은 의존한다.

참고 문헌


1
수정 : 동일한 .m 소스 파일에서 Objective-C는 엄격한 C 수퍼 셋이므로 Objective-CC를 혼합 할 수 있습니다 .
Vinzzz

1
BTW, .mm 은 Objective-C와 C ++ 를 혼합하기위한 것입니다 (C와 C ++은 이름에도 불구하고 두 가지 다른 것입니다). )
Vinzzz

1
객관적인 C와 달리 C ++은 C 수퍼 셋이 아니므로 .cpp 파일에서 C와 C ++를 혼합 할 수는 없습니다. C ++ 및 어셈블리 만
Vality

1
누군가가 Swift 파일을 Objective-C / C ++ 파일에 노출하려고 할 때이 자세한 답변이 도움이되지 않는다는 것을 알게 된 경우 (Xcode는 Swift 헤더 파일을 찾을 수 없다고 불평합니다). Objective-C / C ++ 소스 파일에서 "ProductName / ProductModuleName-Swift.h"가져와야 한다는 것을 알았습니다 . 나는 이것이 developer.apple.com/library/ios/documentation/Swift/Conceptual/…에
AeroBuffalo

좋은 지적. 이러한 언어를 혼합 한 작업중인 프로젝트는 stackoverflow.com/a/32546879/218152를 참조하십시오 .
SwiftArchitect

72

C ++, Objective C 및 Swift 코드를 혼합하는 방법을 보여주는 간단한 Xcode 6 프로젝트를 작성했습니다.

https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console

특히이 예제는 Swift에서 Objective C와 C ++ 함수를 호출합니다.

핵심은 공유 헤더 Project-Bridging-Header.h를 만들고 Objective C 헤더를 거기에 넣는 것입니다.

완전한 예제로 프로젝트를 다운로드하십시오.


이 지안 주셔서 감사합니다!
Jason Elwood

이 예제에 감사하지만 #import "CPlusPlus.h"를 ObjCtoCPlusPlus.mm에서 ObjCtoCPlusPlus.h 파일로 이동하려면 컴파일러에서 다음 오류를 반환합니다. <unknown> : 0 : error : 브리지 헤더를 가져 오지 못했습니다 ' /Users/Ale/Downloads/shared-master/C-ObjC-Swift/Performance_Console/Performance_Console/Performance_Console-Bridging-Header.h '이 가져 오기를 헤더 파일로 옮길 수 있습니까?
Alessandro Pirovano

@API : 아니요, 요점을 놓치고 있습니다. ObjCtoCPlusPlus.h/``.mm``은 C ++ 코드에 Ob-C 인터페이스를 제공하기위한 목적으로 만 존재합니다. 브리지는 여기에서 필수 구성 요소입니다. 포함을 그대로두고 ObjCtoCPlusPlus.…액세스 할 필요가있는 각 C ++ 메소드 의 파일에 메소드를 추가하십시오 . sourcemaking.com/design_patterns/adapter
Slipp D. Thompson

예제를 다운로드했으며 클래스가 예제로 제공하는 STATIC 함수에 환상적이지만 외부에서 사용할 추가 비 정적 함수에 대한 예제를 조정할 수는 없습니다 ... 또한 가능합니까? (수십 년 전에 C ++ 숙제를했는데 ... 지금 당장 가장 날카로운 연필은 아닙니다)
Isaac

31

Objective-C를 건너 뛸 수도 있습니다.중간에 파일을 . .cpp 소스 파일로 C 헤더 파일을 추가하십시오. 헤더 파일에는 C 선언 만 있고 소스 파일에는 C ++ 코드를 포함하십시오. 그런 다음 **-Bridging-Header.h에 C 헤더 파일을 포함시킵니다.

다음 예제는 C ++ 객체 (struct Foo)에 대한 포인터를 반환하므로 Swift는 전역 공간에 struct Foo를 정의하지 않고 COpaquePointer에 저장할 수 있습니다.

Foo.h 파일 (Swift에서 볼 수 있음-브리징 파일에 포함됨)

#ifndef FOO_H
#define FOO_H

// Strictly C code here.
// 'struct Foo' is opaque (the compiler has no info about it except that 
// it's a struct we store addresses (pointers) to it.
struct Foo* foo_create();
void foo_destroy(struct Foo* foo);

#endif

내부 소스 파일 Foo.cpp (Swift에서는 보이지 않음) :

extern "C"
{
#include "Foo.h"
}
#include <vector>

using namespace std;

// C++ code is fine here. Can add methods, constructors, destructors, C++ data members, etc.
struct Foo
{
   vector<int> data;
};

struct Foo* foo_create()
{
   return new Foo;
}

void foo_destroy(struct Foo* foo)
{
    delete foo;
}

1
이 답변은받을 자격이 방법은 더 upvotes을. 정말 유용합니다.
rsp1984

헤더 파일 자체에 extern "C"포함되지 않고 헤더가 포함 된 위치에서 헤더를 감싸는 것을 처음 봤습니다 #ifdef. 훌륭한!
dcow

27

Swift, Objective-C 및 C ++를 사용하여 예제 프로젝트를 조금 만들었습니다. iOS에서 OpenCV 스티칭을 사용하는 방법에 대한 데모입니다. OpenCV API는 C ++이므로 Swift에서 직접 대화 할 수 없습니다. 구현 파일 인 Objective-C ++ 인 작은 래퍼 클래스를 사용합니다. 헤더 스위프트가 직접 대화 할 수 있도록 파일, 오브젝티브 C 깨끗합니다. C ++-ish 파일을 Swift가 상호 작용하는 헤더로 간접적으로 가져 오지 않도록주의해야합니다.

프로젝트는 다음과 같습니다 : https://github.com/foundry/OpenCVSwiftStitch


나는 이것이 Swift와 함께 타사 라이브러리 KudanCV를 사용하려고 오늘 겪었던 문제에 대한 답변이라고 생각합니다. 브리징 헤더는 C ++ 라이브러리 또는 파일에서 가져온 <memory> <strings> 및 <vectors>로 가져 오기가 포함 된 .h 파일을 가져옵니다. 결과적으로 Swift 코드는 컴파일되지 않습니다. 누군가이 문제를 해결할 방법이 있는지 말해 주거나 Objective-C
Rocket Garden의

1
@RocketGarden-KudanCV 헤더 파일은 C ++입니다. 예제 래퍼 클래스와 같은 방식으로 작동하는 래퍼를 작성할 수 있습니다. 또는 objective-C ++ (Objective-C 헤더 포함)로 KudanCV와 통신해야하는 해당 부분을 다시 작성하십시오. KudanCV와 관련이없는 프로젝트의 해당 부분을 다시 작성할 필요가 없습니다.
파운드리

고마워, 나는 약 5 분 후에 그것을 깨달았지만 다른 사람들을 위해 기록하는 것이 유용합니다.
Rocket Garden

13

C ++ / 빠른 통신을 자동화하기 위해 clang 도구를 사용하려고 시도했습니다. C ++ 클래스를 신속하게 인스턴스화하고 C ++ 클래스를 상속하며 가상 메소드를 신속하게 재정의 할 수도 있습니다.
Objective-C / Objective-C ++ 브리지를 신속하고 신속하게 생성하기 위해 내보내려는 C ++ 클래스를 구문 분석합니다.

https://github.com/sandym/swiftpp




4

아니요, 단일 파일이 아닙니다.

그러나 정적 라이브러리 나 프레임 워크가 없어도 Swift Projects에서 C ++을 사용할 수 있습니다. 다른 사람들이 말했듯이, 핵심은 C로 표시된 C 호환 C ++ 헤더를 extern "C"{} 트릭 과 호환하는 Objective-C 브리징 헤더를 만드는 것 입니다.

비디오 자습서 : https://www.youtube.com/watch?v=0x6JbiphNS4


2

다른 답변은 약간 부정확합니다. 실제로 Swift와 [Objective-] C [++]를 같은 파일에 혼합 할 수는 있지만 예상 한대로는 아닙니다.

이 파일 (c.swift)는 모두 유효한 실행 파일로 컴파일 swiftc c.swiftclang -x objective-c c.swift

/* /* */
#if 0
// */
import Foundation
print("Hello from Swift!")
/* /* */
#endif
#include <stdio.h>
int main()
{
    puts("Hello from C!");
    return 0;
}
// */

샘플 코드는 C ++가 아닌 C로되어 있습니다. <iostream> 예제 IMHO를 사용하는 것이 좋습니다.
kakyo

2

많은 트릭 중 하나는

브리징 obj-c ++ 파일에 별도의 헤더 가 필요 합니다 ...

@interface와 @implementation을 일반적인 .mm 파일과 동일한 .mm 파일에 넣을 수는 없습니다.

브리징 헤더 파일에는

#import "Linkage.hpp"

Linkage.hpp에는 Linkage에 대한 @interface가 있고 Linkage.mm에는 .mm에 ​​대한 @implementation이 있습니다.

그리고

... 실제로 Linkage.hpp에 "yourCpp.hpp"를 #include 하지 않습니다 .

#include "yourCpp.hpp"Linkage.hpp 파일이 아닌 Linkage.mm 파일 에만 넣습니다 .

많은 온라인 예제 / 튜토리얼에서 작가는 @interface와 @implementation을 종종 .mm 파일에 넣습니다.

매우 간단한 cpp 브리징 예제에서 작동하지만

문제는:

yourCpp.hpp에 c ++ 기능이 모두 있으면 (예 : 첫 번째 줄 #include <something>) 프로세스가 실패합니다.

그냥하지만 하지 않는#include "yourCpp.hpp"링크가에서 헤더 파일 (그것의 미세 분명히 당신이 필요합니다의 .mm 파일에 그것을 가지고) - 그것은 작동합니다.

불행히도 이것은 전체 과정에서 한 가지 팁 일뿐입니다.


1

이것이 누군가에게 도움이되는 경우, 간단한 Swift 명령 줄 유틸리티에서 간단한 C ++ 정적 라이브러리를 호출하는 방법에 대한 간단한 자습서도 있습니다. 이것은 실제로 개념적인 코드 조각을 증명하는 것입니다.

Objective-C가 필요 없으며 Swift와 C ++ 만 있습니다. C ++ 라이브러리의 코드는 extern "C"연결로 함수를 구현하는 C ++ 래퍼에 의해 호출됩니다. 그런 다음이 함수는 브리징 헤더에서 참조되고 Swift에서 호출됩니다.

http://www.swiftprogrammer.info/swift_call_cpp.html을 참조 하십시오


1

Swift Programming Language의 변경 사항 및 사용자가 볼 수있는 개선 사항에 대한 제안을 유지 관리 하는 공식 리소스에서 SE-0038 에 대한 링크를 제공하고 있습니다.

현재 상태는 승인되었지만 아직 예약되지 않은 기능 요청입니다.

이 링크는이 기능을 찾는 사람을 올바른 방향으로 안내합니다.

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