Opracowałem doskonale wykonalną odpowiedź. Stopień czystości zależy wyłącznie od tego, ile pracy chcesz wykonać.
Najpierw weź swoją klasę C ++ i utwórz funkcje „wrappera” języka C, aby z nią współpracować. Na przykład, jeśli mamy tę klasę 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);
};
Następnie implementujemy te funkcje 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;
}
Nagłówek mostu zawiera wtedy:
#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
W Swift możemy teraz utworzyć instancję obiektu i wchodzić z nim w interakcję w następujący sposób:
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!
Tak więc, jak widać, rozwiązaniem (które w rzeczywistości jest raczej proste) jest utworzenie opakowań, które utworzą instancję obiektu i zwrócą wskaźnik do tego obiektu. Można to następnie przekazać z powrotem do funkcji opakowujących, które mogą z łatwością traktować go jako obiekt zgodny z tą klasą i wywoływać funkcje składowe.
Czystsze
Chociaż jest to fantastyczny początek i udowadnia, że użycie istniejących klas C ++ z trywialnym mostkiem jest całkowicie wykonalne, może być nawet czystsze.
Oczyszczenie tego oznaczałoby po prostu usunięcie UnsafeMutablePointer<Void>kodu ze środka naszego kodu Swift i zamknięcie go w klasie Swift. Zasadniczo używamy tych samych funkcji opakowujących C / C ++, ale łączymy je z klasą Swift. Klasa Swift przechowuje odwołanie do obiektu i po prostu przekazuje wszystkie wywołania metod i atrybutów przez most do obiektu C ++!
Po wykonaniu tej czynności cały kod mostkujący jest całkowicie zamknięty w klasie Swift. Mimo że nadal używamy mostka C, efektywnie używamy obiektów C ++ w sposób przejrzysty bez konieczności ponownego kodowania ich w Objective-C lub Objective-C ++.