Swift 3.0 에서 C 언어 API 호출

Swift 를 사용 하여 프로그램 을 만 들 때 C 의 API 를 호출 할 때 가 있 습 니 다. 많은 글 을 보 았 습 니 다. 대부분 일반적인 원리 입 니 다. 여기 서 바로 올 라 와 서 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)

좋은 웹페이지 즐겨찾기