스위프트의 C++ 클래스와 교류
저는 C++로 작성된 중요한 수업 라이브러리를 가지고 있습니다.나는 그것들을 스위프트 코드로 다시 쓰는 것보다 스위프트 내의 어떤 종류의 브리지를 통해 사용하려고 합니다.주된 동기는 C++ 코드가 여러 플랫폼에서 사용되는 핵심 라이브러리를 나타낸다는 것입니다.사실상 저는 핵심 기능이 OS X에서 작동할 수 있도록 스위프트 기반 UI를 만드는 것입니다.
스위프트의 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 */
스위프트 코드는 이제 함수를 직접 호출할 수 있습니다.
let type = String.fromCString(imageType(filename))
let dump = String.fromCString(hexdump(filename))
제 질문은 좀 더 구체적입니다.Swift 내에서 C++ 클래스를 인스턴스화하고 조작하려면 어떻게 해야 합니까?이것에 관해 출판된 것을 찾을 수 없는 것 같습니다.
저는 완벽하게 관리할 수 있는 답을 찾았습니다.얼마나 깨끗했으면 좋겠는지는 전적으로 얼마나 많은 일을 하고 싶은지에 따라 결정됩니다.
먼저 C++ 클래스를 수강하고 C "wrapper" 기능을 만들어 인터페이스를 합니다.예를 들어, 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>
우리의 스위프트 코드 중간부터 그것을 스위프트 클래스로 캡슐화합니다.기본적으로, 우리는 동일한 C/C++ 래퍼 기능을 사용하지만 스위프트 클래스와 인터페이스합니다.Swift 클래스는 객체 참조를 유지하며 기본적으로 모든 메서드 및 속성 참조 호출을 브리지를 통해 C++ 객체로 전달합니다!
이렇게 하면 모든 브리징 코드가 스위프트 클래스에 완전히 캡슐화됩니다.아직 C 브리지를 사용하고 있지만 Objective-C 또는 Objective-C++에 기록할 필요 없이 C++ 객체를 투명하게 사용하고 있습니다.
스위프트는 현재 C++ 인터럽트가 없습니다.이것은 장기적인 목표이지만 가까운 미래에 일어날 가능성은 매우 낮습니다.
자신만의 해결책 외에 또 다른 방법이 있습니다.c++ code는 objective-c+에 직접 전화하거나 작성할 수 있습니다.
따라서 C++ 코드 위에 목적-C++ 래퍼를 만들고 적합한 인터페이스를 만들 수 있습니다.
그럼 swift code에서 objective-C++ code를 호출합니다.objective-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++ 클래스로 감싸야 할 것입니다.
그럼 보통 objc를 swift에서 호출할 때 사용하는 bridging header.
언급URL : https://stackoverflow.com/questions/35229149/interacting-with-c-classes-from-swift
'programing' 카테고리의 다른 글
Oracle 및 Postgre의 쓰기 Skew 변칙SQL이 트랜잭션을 롤백하지 않음 (0) | 2023.10.27 |
---|---|
c에서 시간 지연을 실행합니다. (0) | 2023.10.27 |
워드프레스 = 강력한 결합에서 디스크를 전통적인 포럼으로 활용하기 (0) | 2023.10.27 |
Angular Resources Service를 통한 JSON 읽기 (0) | 2023.10.27 |
ORA-22275 오류: 잘못된 LOB 로케이터가 지정되었습니다. (0) | 2023.10.27 |