Swift 3.0 에서 C 언어 API 호출
다음 실전 을 바로 시작 하 겠 습 니 다.
void callback(void (* funcPtr)(void *), void * user);
swift 파일 에서 호출 하려 면 코드 는 다음 과 같 습 니 다.
class Person {
func eat() {
print(#file, #line, "eat now")
}
}
func callbackFunc(user: UnsafeMutableRawPointer?) {
if user == nil { return }
let userPtr = user!.assumingMemoryBound(to: Person.self)
userPtr.pointee.eat()
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var user = Person()
let userPtr = withUnsafeMutablePointer(to: &user, {return $0})
callback(callbackFunc, userPtr)
}
}
콜백 의 첫 번 째 매개 변 수 는 반환 값 형식 이 Void 이 고 매개 변수 유형 이 Void 인 함수 포인터 이 며 두 번 째 매개 변 수 는 void * (유형 포인터 없 음) 입 니 다.C 와 Swift 3.0 의 포인터 대조 보기, void = UnsafeMutable RawPointer?
Swift 에 서 는 함수 와 외부 대상 을 캡 처 하지 않 은 패 킷 만 C 함수 포인터 의 실제 인삼 으로 사용 할 수 있 으 며, 클래스 의 구성원 방법, 외부 대상 을 캡 처 하 는 패 킷 은 C 함수 포인터 의 실제 인삼 으로 사용 할 수 없습니다.그래서 콜 백 Func 함 수 를 만 들 었 습 니 다.
func callbackFunc(user: UnsafeMutableRawPointer?)
UnsafeMutable RawPointer 를 받 습 니까?형식의 매개 변수, assuming Memory Bound 는 UnsafeMutableRawPointer 형식 을 UnsafeMutablePointer 형식 으로 변환 할 수 있 습 니 다.
let userPtr = user!.assumingMemoryBound(to: Person.self)
userPtr 는 user 를 가리 키 는 지침 입 니 다. userPtr. pointee 는 이 지침 이 가리 키 는 대상 입 니 다. user 입 니 다. 유형 은 Person 입 니 다. 따라서 지침 이 가리 키 는 대상 을 얻 으 려 면 먼저 지침 을 UnsafeMutablePointer 유형 으로 바 꾸 고 pointee 속성 으로 그 가 가리 키 는 대상 을 얻 을 수 있 습 니 다.
콜백 두 번 째 매개 변수 user 대상 의 지침, 대상 지침 을 가 져 오 는 방법
let userPtr = withUnsafeMutablePointer(to: &user, {return $0})
이 때 userPtr 는 user 를 가리 키 는 지침 으로 UnsafeMutablePointer 형식 으로 Swift 에서 UnsafeMutablePointer 형식의 인 자 를 UnsafeMutableRawPointer 형식 에 전송 할 수 있 습 니 다.이렇게 하면 userPtr 는 두 번 째 매개 변수 로 callback 함수 에 들 어 갈 수 있 습 니 다.
C 언어의 API 내부 에서 어떤 조작 을 했 는 지 우 리 는 알 필요 가 없다. 우 리 는 요구 에 따라 함 수 를 호출 하면 우리 의 목적 을 달성 하고 C 언어 API 와 쉽게 상호작용 할 수 있다.
위의 방법 만 으로 는 부족 합 니 다. 다음 코드 를 보 세 요.
class Person {
func eat() {
print(#file, #line, "eat now")
}
}
func callbackFunc(userPtr: UnsafeMutableRawPointer?) {
if userPtr == nil { return }
let user = Unmanaged.fromOpaque(userPtr!).takeRetainedValue()
user.eat()
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var user = Person()
let userPtr = Unmanaged.passRetained(user).toOpaque()
callback(callbackFunc, userPtr)
}
}
이것 은 더욱 표준 적 이 고 안전 한 쓰기 입 니 다. 이렇게 userPtr 의 유형 은 바로 UnsafeMutable RawPointer 이 고 callback 의 요구 에 더욱 부합 합 니 다.
let userPtr = Unmanaged.passRetained(user).toOpaque()
Unmanaged 구조 체 의 정적 함수 passRetained () 는 retained 가 이 대상 을 가리 키 는 지침 을 만 듭 니 다. 그러면 C 에서 호출 될 때 이 대상 이 거기에 있 고 소각 되 지 않 습 니 다. 이 방법 은 Unmanaged 의 인 스 턴 스 변 수 를 만 든 다음 에 toOpaque () 방법 을 통 해 UnsafeMutable Raw Pointer 로 전환 할 수 있 습 니 다.
let user = Unmanaged.fromOpaque(userPtr!).takeRetainedValue()
언 매 니 지 드 의 상 반 된 방법 으로 user 대상 을 꺼 내 는 방법 은 더욱 안전 하고 대상 이 전달 과정 에서 계속 존재 하고 대상 을 직접 얻 을 수 있다.
Swift 와 C 의 유형 대 조 를 추가 합 니 다.
C 문법
Swift 문법
const Type *
UnsafePointer
Type *
UnsafeMutablePointer
Void *
UnsafeMutableRawPointer or UnsafeRawPointer
참고 자료:http://blog.csdn.net/zkh90644/article/details/52819002 http://blog.csdn.net/zenny_chen/article/details/52166046 Using Swift with Cocoa and Objective-C(Swift 3)
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.