C ++로 작성된 중요한 클래스 라이브러리가 있습니다. 나는 그것들을 Swift 코드로 재 작성하기보다는 Swift 내의 어떤 유형의 브릿지를 통해 사용하려고합니다. 주요 동기는 C ++ 코드가 여러 플랫폼에서 사용되는 핵심 라이브러리를 나타내는 것입니다. 사실상 저는 OS X에서 핵심 기능이 작동 할 수 있도록 Swift 기반 UI를 만들고 있습니다.
“Swift에서 C ++ 함수를 어떻게 호출합니까?”라는 다른 질문이 있습니다. 이것은 내 질문 이 아닙니다 . C ++ 함수에 연결하려면 다음이 잘 작동합니다.
“C”를 통해 브리징 헤더 정의
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const char *hexdump(char *filename);
const char *imageType(char *filename);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
Swift 코드는 이제 함수를 직접 호출 할 수 있습니다.
let type = String.fromCString(imageType(filename))
let dump = String.fromCString(hexdump(filename))
내 질문은 더 구체적입니다. Swift 내에서 C ++ 클래스 를 인스턴스화하고 조작하려면 어떻게 해야합니까? 여기에 게시 된 내용을 찾을 수없는 것 같습니다.
답변
완벽하게 관리 할 수있는 답변을 찾았습니다. 이것이 얼마나 깨끗하길 바라는지는 전적으로 당신이 기꺼이 할 일의 양에 달려 있습니다.
먼저 C ++ 클래스를 가져 와서 인터페이스 할 C “래퍼”함수를 만듭니다. 예를 들어,이 C ++ 클래스가있는 경우 :
class MBR {
std::string filename;
public:
MBR (std::string filename);
const char *hexdump();
const char *imageType();
const char *bootCode();
const char *partitions();
private:
bool readFile(unsigned char *buffer, const unsigned int length);
};
그런 다음 다음 C ++ 함수를 구현합니다.
#include "MBR.hpp"
using namespace std;
const void * initialize(char *filename)
{
MBR *mbr = new MBR(filename);
return (void *)mbr;
}
const char *hexdump(const void *object)
{
MBR *mbr;
static char retval[2048];
mbr = (MBR *)object;
strcpy(retval, mbr -> hexdump());
return retval;
}
const char *imageType(const void *object)
{
MBR *mbr;
static char retval[256];
mbr = (MBR *)object;
strcpy(retval, mbr -> imageType());
return retval;
}
브리지 헤더에는 다음이 포함됩니다.
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const void *initialize(char *filename);
const char *hexdump(const void *object);
const char *imageType(const void *object);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
Swift에서 이제 객체를 인스턴스화하고 다음과 같이 상호 작용할 수 있습니다.
let cppObject = UnsafeMutablePointer<Void>(initialize(filename))
let type = String.fromCString(imageType(cppObject))
let dump = String.fromCString(hexdump(cppObject))
self.imageTypeLabel.stringValue = type!
self.dumpDisplay.stringValue = dump!
보시다시피 해결책 (실제로는 다소 간단합니다)은 개체를 인스턴스화하고 해당 개체에 대한 포인터를 반환하는 래퍼를 만드는 것입니다. 그런 다음 래퍼 함수로 다시 전달되어 해당 클래스를 준수하는 객체로 쉽게 처리하고 멤버 함수를 호출 할 수 있습니다.
더 깨끗하게 만들기
이것은 환상적인 시작이며 사소한 브리지로 기존 C ++ 클래스를 사용하는 것이 완전히 가능하다는 것을 증명하지만 더 깔끔 할 수 있습니다.
이를 정리하면 UnsafeMutablePointer<Void>
Swift 코드 중간에서를 제거하고 이를 Swift 클래스로 캡슐화합니다. 기본적으로 동일한 C / C ++ 래퍼 함수를 사용하지만 Swift 클래스와 인터페이스합니다. Swift 클래스는 객체 참조를 유지하고 기본적으로 모든 메서드 및 속성 참조 호출을 브리지를 통해 C ++ 객체로 전달합니다!
이렇게하면 모든 브리징 코드가 Swift 클래스에 완전히 캡슐화됩니다. 여전히 C 브리지를 사용하고 있지만 Objective-C 또는 Objective-C ++로 다시 코딩하지 않고도 C ++ 객체를 투명하게 효과적으로 사용하고 있습니다.
답변
Swift에는 현재 C ++ interop이 없습니다. 장기적인 목표이지만 가까운 장래에 일어날 가능성은 거의 없습니다.
답변
자신의 솔루션 외에도 다른 방법이 있습니다. Objective-C ++에서 C ++ 코드를 호출하거나 직접 작성할 수 있습니다.
따라서 C ++ 코드 위에 객관적인 C ++ 래퍼를 만들고 적절한 인터페이스를 만들 수 있습니다.
그런 다음 신속한 코드에서 목표 C ++ 코드를 호출하십시오. 객관적인 C ++ 코드를 작성하려면 파일 확장자를 .m에서 .mm로 바꿔야 할 수 있습니다.
적절할 때 C ++ 객체에 의해 할당 된 메모리를 해제하는 것을 잊지 마십시오.
답변
Scapix Language Bridge 를 사용 하여 C ++를 Swift에 자동으로 연결할 수 있습니다 (다른 언어 중에서). C ++ 헤더 파일에서 직접 즉석에서 자동으로 생성 된 브리지 코드. 다음은 예입니다 .
C ++ :
#include <scapix/bridge/object.h>
class contact : public scapix::bridge::object<contact>
{
public:
std::string name();
void send_message(const std::string& msg, std::shared_ptr<contact> from);
void add_tags(const std::vector<std::string>& tags);
void add_friends(std::vector<std::shared_ptr<contact>> friends);
};
빠른:
class ViewController: UIViewController {
func send(friend: Contact) {
let c = Contact()
contact.sendMessage("Hello", friend)
contact.addTags(["a","b","c"])
contact.addFriends([friend])
}
}
답변
또 다른 답변에서 언급했듯이 ObjC ++를 사용하여 상호 작용하는 것이 훨씬 쉽습니다. .m 및 xcode / clang 대신 파일 이름을 .mm로 지정하면 해당 파일의 C ++에 액세스 할 수 있습니다.
ObjC ++는 C ++ 상속을 지원하지 않습니다. ObjC ++에서 C ++ 클래스를 하위 클래스로 만들고 싶지만 할 수 없습니다. C ++로 서브 클래스를 작성하고 ObjC ++ 클래스를 감싸 야합니다.
그런 다음 일반적으로 swift에서 objc를 호출하는 데 사용하는 브리징 헤더를 사용합니다.