콘텐츠로 건너뛰기
Home » C API

C API

버퍼 포인터 이해하기

C에서 특정한 T타입의 배열은 메모리 상에서 연속적인 공간입니다. 이 때문에 정적 배열이든 동적 배열이든 배열을 액세스하는 것은 필연적으로 포인터와 관련됩니다. 반면 Swift의 배열에서 원소들은 반드시 이런 식으로 배치되지는 않습니다. C의 배열이 단지 원소값이 나란히 배치된 메모리 영역임에 비해 Swift의 배열은 struct로 구성되는 보다 복잡한 내부 구조를 가지고 있습니다.

이 때 T 타입이 차지하는 바이트 수가 고정되어 있으므로 배열의 시작번지와 인덱스 값을 알고 있다면 해당 인덱스에 위치한 값을 액세스할 수 있습니다. C에서 배열 이름은 암묵적으로 배열의 시작번지를 의미하므로, arr[i]로 표현되는 i 번째 원소의 값은 실제 컴파일러는 *(arr + i) 로 변환하여 접근합니다.

Swift에서도 UnsafePointer를 사용하여 포인터를 다룰 수 있는데, 이 때 범위(capacity, Pointee 타입의 메모리 사이즈 x 원소의 개수)내에는 동일타입을 구성하는 값들이 연속하여 배치되어 있습니다. 따라서 (ptr + i).pointee 와 같은 식으로 i 번째 원소에 대해 액세스가 가능합니다. 이것은 C의 접근방법과 매우 유사합니다. 하지만 이것은 단순한 메모리 연속체에서 특정 지점을 액세스하는 법일 뿐, Swift의 배열을 다루는 것과는 차이가 있습니다. Swift의 배열은 원소가 연속해있으면서 Sequence, Collection 프로토콜에 의한 여러가지 연산을 지원받습니다.

더 보기 »버퍼 포인터 이해하기

SQLite3 C API를 Swift에서 사용하는 방법

Swift에서 SQLite3를 사용하는 방법은 크게 두 가지이다. 하나는 Objective-C에서 SQLite3를 액세스하는 래퍼 클래스를 작성하고, 이 것을 Swift 프로젝트에 포함시켜서 컴파일하는 것이다. Swift는 Objective-C와 자연스럽게 상호호환되기 때문에 Objective-C에 친숙하다면 이 방법도 나쁘지 않다.

관련글 : Objective-C 래퍼를 통해 Swift에서 SQLite3를 사용하는 법

다른 한가지 방법으로는 sqlite3.h 헤더를 Swift에서 반입하여 Swift에서 SQLite3 C API를 바로 사용하는 것이다. 결국 업어치나 메치나 똑같은 것이기는 한데, Swift에서 C API를 직접 사용하는 것은 Swift와 C의 연계 방식에 대한 이해가 필요하다. 이 글에서는 Swift에서 Sqlite3를 사용하기 위해 필요한 배경 지식들에 대해서 살펴볼 예정이다. SQLite3 API에 대한 자세한 설명이 필요할 수 있는데, 이 내용은 Objective-C에서 SQLite3를 사용하는 법을 다룬 위 링크에서 대략 소개하고 있으며, 이 글에서는 최소한 SQLite3 API에 대해 알고 있다고 전제하겠다.

SQLite3 C API를 사용하여 쿼리를 실행하는 결과에 대해서는 다음의 과정을 거친다.

  1. 데이터베이스 연결
  2. 쿼리 컴파일 및 쿼리 바인딩
  3. 쿼리 실행 및 각 Row의 데이터 획득
  4. 연결닫기
더 보기 »SQLite3 C API를 Swift에서 사용하는 방법

Swift에서 포인터를 함수에 전달하는 법

기본적으로 Swift는 C(그리고 Objective-C)와 호환이 가능하다. 이를 위해 C의 각 데이터 타입에 대응할 수 있는 Swift 타입들을 정의해 두고 있다. 따라서 C로 작성된 라이브러리를 사용할 수 있고, 이 때 해당 라이브러리의 함수들은 적절하게 Swift 버전에 맞는 시그니처로 변환된다. 예를 들어 문자열의 길이를 구하는 C함수인 strlen 함수를 Swift에서 호출하고 싶은 상황을 가정해보자. strlen 함수의 원형과 반입된 버전의 함수는 각각 아래와 같은 형태로 만들어질 것이다. 자 그러면 Swift 문자열의 길이를 저 함수를 사용해서 구하고 싶은 상황이라고 하자. 문자열을 어떻게 UnsafePointer<UInt> 로 변환할… 더 보기 »Swift에서 포인터를 함수에 전달하는 법