Я розробив цілком керовану відповідь. Наскільки чистою ви хотіли б, щоб це було, цілком залежить від того, скільки роботи ви готові зробити.
По-перше, візьміть свій клас 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
Від 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, ми ефективно використовуємо об'єкти C ++ прозоро, не маючи необхідності перекодувати їх у Objective-C або Objective-C ++.