티스토리 뷰

안녕하세요.

사실은 C++ 로 framework 를 작성하는 방법을 작성하려고 했는데 

글이 너무 길어지는 바람에 우선 간단한 것 먼저 확인할까 합니다. 

(framework는 정리하다 보니 내용이 너무 길어서 고민중입니다.)

 

그래서 오늘은 간단하게 Xcode 프로젝트에서 C++ 이 잘 작동하는지 알아봅시다. 

다만 Obj-C 프로젝트 swift 프로젝트에서 적용법이 살짝 다르기 때문에 

나눠서 해보도록 하겠습니다. 

 

* 주의 *

- 저장소를 이용하는 부분의 경우 권한 문제로 작동하지 않는 경우가 있습니다. (ex. fopen

- 그래서 이런 부분은 ObjC나 swift 를 이용해 따로 작성하는걸 권장드립니다.

 

그럼 오늘의 실험을 도와줄 C++ 코드를 먼저 작성해봅시다. 

 

0. 프로젝트에 C++ 파일 만들기 (공통)

- 만약 C++ 파일이 있으시면 드래그앤드롭 으로 추가해주셔도 됩니다.

여기 이걸로 추가해줍시다.

- 여기 보시면 C++ 파일이 있습니다. 이걸로 만들어 줍니다.  

만드실때 C++ Header 만들기 옵션도 눌러주세요.

- 그 다음 테스트 할 코드를 작성해줍시다. 

(다만 저는 C++ 은 잘 몰라서  틀린 문법이 있을 수 있습니다.) 

* CPlusPlus.hpp (헤더로 이걸로 연결하신다고 보면 됩니다.)

#ifndef CPlusPlus_hpp
#define CPlusPlus_hpp

#include <stdio.h>
#include <iostream> // 따로 추가해야 std 가능
class CppClass {
public:
    CppClass();
    const char* testCPP();
};
#endif /* CPlusPlus_hpp */

* CPlusPlus.cpp

#include "CPlusPlus.hpp"
CppClass::CppClass() {
    std::cout << "생성" << std::endl;
}
const char* CppClass::testCPP() {
    std::cout << "Hello, Xcode! I'm Cpp" << std::endl;  // 문자열 출력
    return "안녕 나는 C++";
}

진짜 간단하죠?

 

Tip . 경험담 

처음에는 std::string 이라는 타입을 사용했다가 const char* 로 바꾸었는데 

swift 에서 std::string 을 가져오는 부분이 다소 복잡해서 바꿔주었습니다. 

 

C++ 함수의 리턴값을 화면에 보여주는 걸 목표로 해보겠습니다. 

* 기본적인 UILabel 은 미리 생성된 상태입니다. 

 

1. Obj-C 프로젝트에서 C++ 사용하기 

- 사용할 곳에 헤더를 추가해주세요. (저는 메인 ViewController 헤더에 추가했습니다.)

#import <UIKit/UIKit.h>
#import "CPlusPlus.hpp" // 여기 보이시나요?
@interface ViewController : UIViewController
	@property (weak, nonatomic) IBOutlet UILabel *mainLbl;
@end

- (매우 중요) 파일의 형식을 변형해주세요.

파일 형식과 타입 주의하세요!!!

Q. 왜 바꿔야 하나요?

A. 저희가 일반적으로 사용하는 .m 형식은 C++ 을 연결하지 못합니다.

     그래서 그걸 가능하게 해주는 .mm 으로 바꿔야 호출했을때 정상적인 사용이 가능합니다. 

 

- C++ 클래스를 선언해서 함수를 불러와 줍니다. 

CppClass* cpp = new CppClass();// C++ 은 alloc init 이 아닌 new 로 해주세요
_mainLbl.text = [[NSString alloc]initWithCString:cpp->testCPP() encoding:NSUTF8StringEncoding];

- 실행하여 결과를 확인합니다. 

성공적으로 나옵니다.

2. Swift 프로젝트에서 C++ 사용하기 

- 마찬가지로 프로젝트에 C++ 파일을 만들어줍니다.

- 그런데 0번을 실행하다보면 아래 같은 창을 보시게 될겁니다.

매우매우 중요합니다.

**이거 뜨면 Create 무조건 눌러주세요 그게 매우 편합니다.**

Q. 저는 저런거 안뜨는데요?

A. 그러면 빈 헤더 파일 하나 만들어주시고 Build Settings 로 들어가서 아래 검색해주세요.

SWIFT_OBJC_BRIDGING_HEADER

그 다음 거기에 본인이 생성한 헤더 이름을 맞춰서 세팅에 작성해주셔야 합니다.

매우중요합니다. 이름 조심하세요.

Q. 이걸 왜 해야 하나요?

A. Swift 는 다른 언어와 연결하기 위해서는 Bridging Header라는 친구가 반드시 필요합니다. (특히 ObjC랑 연결시)

그래서 이게 없으면 연결이 되지 않습니다. 

 

* 설정 변경 

저희는 C 가 아니라 C++ 이기 때문에 그냥하시면 빨간 줄이 계속 나올수있습니다

방법은 여러가지가 있지만 가장 간단한 방법은 Build Settings 에서 아래 설정을 변경하는 방법입니다. 

(간단한 경우에는 이걸로 가능하지만 불가능한 경우 C++ 언어를 ObjC로 감싸주시는등 다른 방법을 써야합니다.)

SWIFT_OBJC_INTEROP_MODE

아래 이미지처럼 바꿔주시면 인식이 됩니다.

이렇게 해주시면 인식이 됩니다.

 

자 그럼 이제 Bridging-Header 에 우리가 무얼 연결할껀지 적어야겠죠?

#import "CPlusPlus.hpp"

 

위처럼 자신이 연결하고자하는 헤더를 저런 식으로 작성해주시면 되요.

이러면 해당 프로젝트 전체에서 저 헤더의 내용을 접근할 수 있습니다. 

(ObjC 와는 조금 다르죠?)

 

그럼 이제 아무 UILabel 에 연결 후 Obj-C 처럼 실행해봅시다. 

var cppClassInstance = CppClass()  // var로 선언 주의 
if let cString = cppClassInstance.testCPP(){// 타입으로 인해 한번 감싸기
    let swiftString : String = String(cString: cString)
    mainLbl.text = swiftString// 출력
}

간단히 이렇게 작성하고 돌려봅시다. 

ObjC처럼 잘 나오죠?

 

Obj-C 의 경우에는 아무래도 C 와 연관이 있는 언어다보니 연결할때 어려운 느낌이 별로 없는데 

Swift 의 경우에는 절차가 조금 더 있는 느낌이 있네요. 

 

아무튼 이번에는 C++ 로 iOS 에서 실행을 하는 부분을 해보았습니다. 

 

혹시나 다른 분들께도 도움이 되지 않을까 하는 마음에 

정리해보았는데 생각보다 글이 복잡해보이네요.

 그래도 누군가에게 도움이 되길 바라며 

오늘도 파이팅입니다. 

 

댓글