He elaborado una respuesta perfectamente manejable. Lo limpio que le gustaría que fuera esto se basa completamente en la cantidad de trabajo que esté dispuesto a hacer.
Primero, tome su clase C ++ y cree funciones de "envoltura" de C para interactuar con ella. Por ejemplo, si tenemos esta clase 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);
};
Luego implementamos estas funciones de 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;
}
El encabezado del puente luego contiene:
#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
Desde Swift, ahora podemos instanciar el objeto e interactuar con él así:
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!
Entonces, como puede ver, la solución (que en realidad es bastante simple) es crear contenedores que crearán una instancia de un objeto y devolverán un puntero a ese objeto. Esto luego se puede pasar de nuevo a las funciones contenedoras que pueden tratarlo fácilmente como un objeto conforme a esa clase y llamar a las funciones miembro.
Haciéndolo más limpio
Si bien este es un comienzo fantástico y demuestra que es completamente factible usar clases de C ++ existentes con un puente trivial, puede ser aún más limpio.
Limpiar esto simplemente significaría que eliminamos el UnsafeMutablePointer<Void>
del medio de nuestro código Swift y lo encapsulamos en una clase Swift. Esencialmente, usamos las mismas funciones contenedoras de C / C ++ pero las interconectamos con una clase Swift. La clase Swift mantiene la referencia del objeto y esencialmente solo pasa todas las llamadas de referencia de método y atributo a través del puente al objeto C ++.
Una vez hecho esto, todo el código puente está completamente encapsulado en la clase Swift. Aunque todavía estamos usando un puente C, estamos usando efectivamente objetos C ++ de forma transparente sin tener que recurrir a recodificarlos en Objective-C o Objective-C ++.