태그 보관물: swift

swift

Swift의 C ++ 클래스와 상호 작용 ++로 작성된 중요한

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를 호출하는 데 사용하는 브리징 헤더를 사용합니다.


답변