私は完全に扱いやすい答えを考え出しました。これをどれだけきれいにしたいかは、完全にあなたがやろうとしている仕事の量に基づいています。
まず、C ++クラスを取得し、それとインターフェイスする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ブリッジを使用していますが、Objective-CまたはObjective-C ++での再コーディングに頼ることなく、C ++オブジェクトを透過的に効果的に使用しています。