Ho elaborato una risposta perfettamente gestibile. Quanto pulito vorresti che fosse questo dipende interamente da quanto lavoro sei disposto a fare.
Per prima cosa, prendi la tua classe C ++ e crea funzioni C "wrapper" per interfacciarla con essa. Ad esempio, se abbiamo questa classe 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);
};
Quindi implementiamo queste funzioni 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;
}
L'intestazione del bridge contiene quindi:
#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
Da Swift, ora possiamo istanziare l'oggetto e interagire con esso in questo modo:
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!
Quindi, come puoi vedere, la soluzione (che in realtà è piuttosto semplice) è creare wrapper che istanzeranno un oggetto e restituiranno un puntatore a quell'oggetto. Questo può quindi essere ritrasmesso alle funzioni wrapper che possono facilmente trattarlo come un oggetto conforme a quella classe e chiamare le funzioni membro.
Rendendolo più pulito
Anche se questo è un inizio fantastico e dimostra che è completamente fattibile utilizzare le classi C ++ esistenti con un ponte banale, può essere ancora più pulito.
Ripulirlo significherebbe semplicemente che rimuoviamo UnsafeMutablePointer<Void>
dal centro del nostro codice Swift e lo incapsuliamo in una classe Swift. Essenzialmente, usiamo le stesse funzioni wrapper C / C ++ ma le interfacciamo con una classe Swift. La classe Swift mantiene il riferimento all'oggetto e essenzialmente passa tutte le chiamate di riferimento ai metodi e agli attributi attraverso il bridge all'oggetto C ++!
Fatto ciò, tutto il codice bridging è completamente incapsulato nella classe Swift. Anche se stiamo ancora utilizzando un bridge C, stiamo effettivamente utilizzando oggetti C ++ in modo trasparente senza dover ricorrere a ricodificarli in Objective-C o Objective-C ++.