Eu encontrei uma resposta perfeitamente administrável. O grau de limpeza que você gostaria que isso fosse depende inteiramente de quanto trabalho está disposto a fazer.
Primeiro, pegue sua classe C ++ e crie funções C "wrapper" para fazer a interface com ela. Por exemplo, se tivermos esta 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);
};
Em seguida, implementamos essas funções 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;
}
O cabeçalho da ponte contém:
#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
A partir do Swift, agora podemos instanciar o objeto e interagir com ele assim:
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!
Então, como você pode ver, a solução (que na verdade é bastante simples) é criar wrappers que irão instanciar um objeto e retornar um ponteiro para esse objeto. Isso pode então ser passado de volta para as funções de invólucro, que podem facilmente tratá-lo como um objeto em conformidade com aquela classe e chamar as funções-membro.
Tornando-o mais limpo
Embora seja um começo fantástico e prove que é completamente viável usar as classes C ++ existentes com uma ponte trivial, pode ser ainda mais limpo.
Limpar isso significaria simplesmente que removemos o UnsafeMutablePointer<Void>do meio de nosso código Swift e o encapsulamos em uma classe Swift. Essencialmente, usamos as mesmas funções de wrapper C / C ++, mas as interfaces com uma classe Swift. A classe Swift mantém a referência do objeto e essencialmente apenas passa todas as chamadas de referência de método e atributo através da ponte para o objeto C ++!
Feito isso, todo o código de bridging é completamente encapsulado na classe Swift. Mesmo que ainda estejamos usando uma ponte C, estamos efetivamente usando objetos C ++ de forma transparente, sem ter que recorrer a recodificá-los em Objective-C ou Objective-C ++.