22
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

SwiftでCの配列を使う

Swiftの時代になっても、既存のAPIとの互換性とのために、Cの配列をやりとりするAPIが残っています。

例えば

APIリファレンスで次のようなAPIを調べてみると…

void CGContextSetFillColor ( CGContextRef context, const CGFloat components[] );
func CGContextSetFillColor(_ c: CGContext!,
                         _ components : CConstPointer<CGFloat>)

引数componentsはObjective-CではCGFloatの配列なのに、SwiftのCConstPointer<CGFloat>って何だよって感じですよね。

型の対応

基本的には、Swiftで配列を作って渡せばいいようになっていますが、ちょっと注意が必要な場合もあります。

まずは、公式ドキュメントより、Cの型とSwiftの型との対応を見てみましょう。

Cの型 Swiftの型
const void * CConstVoidPointer
void * CMutableVoidPointer
const Type * CConstPointer<Type>
Type * CMutablePointer<Type>

CMutablePointer<Type>

Cの型はType *です。あらかじめ配列のメモリを確保して、呼び出した関数がそこに文字列を入れてくれるような関数などを思い浮かべてください。
CMutablePointer<Type>の場合は、配列の変数名の先頭に "&" を付けて渡します。

func takesAMutablePointer(x: CMutablePointer<Float>) { /*...*/ }
var a: Float[] = [1.0, 2.0, 3.0]
takesAMutablePointer(&a)

NSString

func getCString(_ buffer: CMutablePointer<CChar>,
      maxLength maxBufferCount: Int,
       encoding encoding: UInt) -> Bool

というAPIを使って、もうちょっと具体的な例を見てみましょう。

let str = "Hello, Swift"
let strLength = Int(countElements(str))
// 文字列の長さ+1の長さの配列を作成
var charArray = CChar[](count: strLength + 1, repeatedValue: 0)
// 配列を渡してCCharを取得
(str as NSString).getCString(&charArray, maxLength: strLength + 1, encoding: NSUTF8StringEncoding)

charArray //[72, 101, 108, 108, 111, 44, 32, 83, 119, 105, 102, 116, 0]

CConstPointer<Type>

Cの型はconst Type *です。Cでconstが付いている配列は値が変更されません。
CConstPointer<Type>の場合は、変数名に何も付けずにそのまま渡します。

func takesAConstVoidPointer(x: CConstVoidPointer)  { /* ... */ }
var a: Float[] = [1.0, 2.0, 3.0]
takesAConstVoidPointer(a)
takesAConstVoidPointer([1.0, 2.0, 3.0])

NSString

class func stringWithCharacters(_ chars: CConstPointer<unichar>,
                         length length: Int) -> Self!

というAPIを使って、もうちょっと具体的な例を見てみましょう。

let unicharArray:unichar[] = [72, 101, 108, 108, 111, 44, 32, 83, 119, 105, 102, 116]
let len = unicharArray.count
let s = NSString.stringWithCharacters(unicharArray, length: len) // "Hello, Swift"

補足

ちなみに、CでNULLポインタになるようにしたいときは、Swiftではnilを渡せばOKです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
22
Help us understand the problem. What are the problem?