Swift의 C ++ 클래스와 상호 작용
C ++로 작성된 중요한 클래스 라이브러리가 있습니다. 나는 그것들을 Swift 코드로 재 작성하기보다는 Swift 내의 어떤 유형의 브릿지를 통해 사용하려고합니다. 주된 동기는 C ++ 코드가 여러 플랫폼에서 사용되는 핵심 라이브러리를 나타내는 것입니다. 사실상 저는 OS X에서 핵심 기능이 작동 할 수 있도록 Swift 기반 UI를 만들고 있습니다.
"Swift에서 C ++ 함수를 어떻게 호출합니까?"라는 다른 질문이 있습니다. 이것은 내 질문 이 아닙니다 . C ++ 함수에 연결하려면 다음이 잘 작동합니다.
"C"를 통해 브리징 헤더 정의
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const char *hexdump(char *filename);
const char *imageType(char *filename);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
Swift 코드는 이제 함수를 직접 호출 할 수 있습니다.
let type = String.fromCString(imageType(filename))
let dump = String.fromCString(hexdump(filename))
내 질문은 더 구체적입니다. Swift 내에서 C ++ 클래스 를 인스턴스화하고 조작하려면 어떻게 해야합니까? 여기에 게시 된 내용을 찾을 수없는 것 같습니다.
완벽하게 관리 할 수있는 답변을 찾았습니다. 이것이 얼마나 깨끗하길 바라는지는 전적으로 당신이 기꺼이 할 일의 양에 달려 있습니다.
먼저 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 /* ImageReader_hpp */
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!
So, as you can see, the solution (which is actually rather simple) is to create wrappers that will instantiate an object and return a pointer to that object. This can then be passed back into the wrapper functions which can easily treat it as an object conforming to that class and call the member functions.
Making It Cleaner
While this is a fantastic start and proves that it is completely feasible to use existing C++ classes with a trivial bridge, it can be even cleaner.
Cleaning this up would simply mean that we remove the UnsafeMutablePointer<Void>
from the middle of our Swift code and encapsulate it into a Swift class. Essentially, we use the same C/C++ wrapper functions but interface them with a Swift class. The Swift class maintains the object reference and essentially just passes all method and attribute reference calls through the bridge to the C++ object!
Having done this, all of the bridging code is completely encapsulated in the Swift class. Even though we are still using a C bridge, we are effectively using C++ objects transparently without having to resort to recoding them in Objective-C or Objective-C++.
Swift has no C++ interop currently. It's a long-term goal, but is very unlikely to happen in the near future.
In addition to your own solution, there is another way to do it. You can call or directly write C++ code in objective-c++.
So if you create an objective-C++ wrapper on top of your C++ code and create a suitable interface
and call objective-C++ code from your swift code. To be able to write objective-C++ code you may have to rename file extension from .m to .mm
Do not forget to release memory allocated by your C++ objects when suitable.
As another answer mentioned, using ObjC++ to interact is much easier. Just name your files .mm instead of .m and xcode/clang, gives you access to c++ in that file.
Note that ObjC++ does not support C++ inheritance. I you want to subclass a c++ class in ObjC++, you can't. You will have to write the subclass in C++ and wrap it around an ObjC++ class.
Then use the bridging header you would normally use to call objc from swift.
You can use Scapix Language Bridge to automatically bridge C++ to Swift (among other languages). Bridge code automatically generated on the fly directly from C++ header files. Here is an example:
C++:
#include <scapix/bridge/object.h>
class contact : public scapix::bridge::object<contact>
{
public:
std::string name();
void send_message(const std::string& msg, std::shared_ptr<contact> from);
void add_tags(const std::vector<std::string>& tags);
void add_friends(std::vector<std::shared_ptr<contact>> friends);
};
Swift:
class ViewController: UIViewController {
func send(friend: Contact) {
let c = Contact()
contact.sendMessage("Hello", friend)
contact.addTags(["a","b","c"])
contact.addFriends([friend])
}
}
참고URL : https://stackoverflow.com/questions/35229149/interacting-with-c-classes-from-swift
'Development Tip' 카테고리의 다른 글
ReactJS : 자식 구성 요소 내부 부모의 setState (0) | 2020.11.05 |
---|---|
테이블 스캔과 클러스터형 인덱스 스캔의 차이점은 무엇입니까? (0) | 2020.11.05 |
TouchableNativeFeedback, TouchableHighlight 또는 TouchableOpacity를 언제 사용합니까? (0) | 2020.11.05 |
Webkit 브라우저에서 TBODY를 스크롤 가능하게 만들기 (0) | 2020.11.05 |
동일한 이름을 가진 두 개의 입력 요소를 갖는 것이 유효합니까? (0) | 2020.11.05 |