Tôi đã tìm ra một câu trả lời hoàn toàn có thể quản lý được. Bạn muốn điều này sạch sẽ như thế nào hoàn toàn dựa trên mức độ công việc bạn sẵn sàng làm.
Đầu tiên, lấy lớp C ++ của bạn và tạo các hàm C "wrapper" để giao tiếp với nó. Ví dụ: nếu chúng ta có lớp C ++ này:
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);
};
Sau đó, chúng tôi triển khai các hàm C ++ sau:
#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;
}
Sau đó, tiêu đề cầu nối chứa:
#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
Từ Swift, bây giờ chúng ta có thể khởi tạo đối tượng và tương tác với nó như sau:
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!
Vì vậy, như bạn có thể thấy, giải pháp (thực ra khá đơn giản) là tạo các trình bao bọc sẽ khởi tạo một đối tượng và trả về một con trỏ cho đối tượng đó. Điều này sau đó có thể được chuyển trở lại các hàm wrapper, có thể dễ dàng coi nó như một đối tượng phù hợp với lớp đó và gọi các hàm thành viên.
Làm cho nó sạch hơn
Mặc dù đây là một khởi đầu tuyệt vời và chứng minh rằng việc sử dụng các lớp C ++ hiện có với một cầu nối nhỏ là hoàn toàn khả thi, nó thậm chí có thể sạch hơn.
Làm sạch điều này đơn giản có nghĩa là chúng tôi loại bỏ UnsafeMutablePointer<Void>
phần giữa mã Swift của chúng tôi và đóng gói nó thành một lớp Swift. Về cơ bản, chúng tôi sử dụng các hàm trình bao bọc C / C ++ tương tự nhưng giao diện chúng với một lớp Swift. Lớp Swift duy trì tham chiếu đối tượng và về cơ bản chỉ chuyển tất cả các lệnh gọi tham chiếu phương thức và thuộc tính thông qua cầu nối đến đối tượng C ++!
Sau khi thực hiện điều này, tất cả mã bắc cầu hoàn toàn được gói gọn trong lớp Swift. Mặc dù chúng ta vẫn đang sử dụng C bridge, chúng ta đang sử dụng hiệu quả các đối tượng C ++ một cách minh bạch mà không cần phải giải mã chúng trong Objective-C hoặc Objective-C ++.