swift만 사용하다가 요새 c 라이브러리를 좀 붙여볼 일들이 있었는데, 예전에 알던 내용이 머리속에서 리셋되어 가물가물한 상태.
연동할 c 함수의 인자가 포인터 타입일때 swift에서 어떻게 전달해야 하는지 다시한번 살펴본다.
호환 타입
| Int32 | int | 32비트 정수 |
| UInt32 | unsigned int | 부호없는 32비트 정수 |
| Int64 | long long | 64비트 정수 |
| UInt64 | unsigned long long | 부호없는 64비트 정수 |
| Int | long | 플랫폼에 따라 32/64 |
| UInt | unsigned long | 플랫폼에 따라 부호없는 32/64 |
| Float | float | 32비트 부동소수점 |
| Double | double | 64비트 부동소수점 |
| Bool | bool | |
| UnsafePointer<T> | T* | 포인터 |
| UnsafeMutablePointer<T> | T* | 변경 가능한 포인터 |
| UnsafeRawPointer | void* | 타입없는 포인터 |
| UnsafeMutableRawPointer | void* | 변경 가능한 타입없는 포인터 |
| OpaquePointer | void* | 구현부를 알수 없는 포인터 |
| String | const char* | 문자열 |
| StaticString | const char* | 컴파일 시점 문자열 |
| @convention(c) 함수형 | c 함수 포인터 | swift 함수 포인터 |
포인터 전달
swift와 타입이 동일한 c 포인터로 전달하는 경우 inout 연산자인 & 를 사용해 값을 전달하면 된다.
이경우 mutable 형태로 전달되기때문에 var 선언된 변수만 동작한다.
// c
void c_function(int* ptr);
// swift
var value: Int = 1
c_function(&value)
포인터형으로 직접 변환해 전달하는 경우
UnsafePointer<T> -> T*
var value: Int = 1
withUnsafePointer(to: &value) { ptr in
c_function(ptr)
}
void*
void* 는 swift에서 RawPointer 형으로 변경해 전달한다
이때 바로 RawPointer를 생성하지 않고, 일반 포인터로 변경하는 스코프 내에서 별도 포인터 생성 후 전달한다.
렇게 감싸지 않으면 swift 에서 포인터가 유효하지 않은 메모리를 참조할 수 있다는 경고가 발생한다.
UnsafePointer<T> -> UnsafeRawPointer -> void*
var value: Int = 1
withUnsafePointer(to: &value) { ptr in
let rawPtr = UnsafeRawPointer(ptr)
c_function(rawPtr)
}
void**
포인터의 포인터이므로, 포인터를 다시 포인터로 감싸야 하는데, void* 를 타입으로하는 포인터(UnsafePointer)를 만들어 준다.
UnsafePointer<T> -> UnsafePointer<UnsafeRawPointer> -> void**
var value: Int = 1
withUnsafePointer(to: &value) { ptr in
let rawPtr = UnsafeRawPointer(ptr)
withUnsafePointer(to: rawPtr) { voidPtr in
c_function(voidPtr)
}
}
const void**
보통 void** 만으론 사용하지 않고, 이중 포인터를 보호하기위해 const void** 를 사용한다.
이경우 void** 에서 void* 부분을 옵셔널 포인터로 다시 바인딩 해줘야 한다.
UnsafePointer<T> -> UnsafePointer<UnsafeRawPointer> -> UnsafePointer<UnsafeRawPointer?> -> const void**
var value: Int = 1
withUnsafePointer(to: &value) { ptr in
let rawPtr = UnsafeRawPointer(ptr)
withUnsafePointer(to: rawPtr) { voidPtrPtr in
voidPtrPtr.withMemoryRebound(to: UnsafeRawPointer?.self, capacity: 1) { constPtrPtr in
c_function(constVoidPtrPtr)
}
}
}
'프로그래밍 > iOS,macOS' 카테고리의 다른 글
| [swift] swift 라이브러리 c 코드에서 연동하기 (0) | 2025.10.18 |
|---|---|
| [swift] 커맨드라인 실행 파일 만들기(swift-argument-parser) (0) | 2025.10.16 |
| SPM Package.swift 관련 요소 목록 (0) | 2025.10.14 |
| [swift] SCNProgram 쉐이더 투명 적용 (0) | 2024.10.31 |
| [swift] SceneKit uv animation (0) | 2024.08.22 |
| [swift] swiftui fileImpoter로 파일 선택하기 (0) | 2024.08.08 |
| [concurrency] Task, TaskGroup, task timeout (0) | 2023.02.28 |
| [swift] sorted array 에 값 추가 (0) | 2022.06.10 |
| [concurrency] swift async/await (0) | 2022.05.13 |
| [Combine] 콜백 기반 여러 처리 결과를 배열로 받기 (0) | 2022.03.20 |