Swiftã³ã¼ãã¨Cé¢æ°ã¨ã®éã§ã®ãã¼ã¿å¤æã«ã¤ãã¦
Xcode 6.0 Beta
前回ã¯ãSwiftã³ã¼ãå ã§èªä½Cé¢æ°ãå¼ã³åºãããæ¹ã調ã¹ã¦ããã¹ãã³ã¼ããæ²è¼ããã
ãã¾ãåããã¨ã¯åãããããã¾ã詳細ãªé¨åã«ã¤ãã¦ã¯è§£èª¬ã§ããªãã£ããä»åã¯ããããªãã¤ã³ãã¨ãããã主ã«åå¤æã«ã¤ãã¦ããã®ã¨ãè¦å´ãããã¨ãè£è¶³èª¬æãããã¨æãã
説æã¨ã¯ãã£ã¦ããç§èªèº«ãã¾ã ã¾ã Swiftãå¦ç¿ãå§ããã°ãããªã®ã§ã誤ã£ããã¨ãè¨è¿°ããã¦ãããããã£ã¨å¹çã®è¯ãããæ¹ãããå¯è½æ§ã¯ååã«ããããããæ°ã¥ãã®æ¹ãããããæ¯éãææé¡ãããã
ããã§ã¯ãååä½æããSwiftã®ãã¹ãã³ã¼ãããã³ã¡ã³ããæé¤ãããã¤ã³ãã¨ãªãè¡ã«çªå·ãã¤ãã¦ãã¼ã¯ãããã®ã以ä¸ã«æ²è¼ãããå¾ã§ãã³ã¡ã³ãã¨ãã¦ã¤ããçªå·ã®é¨åã«ã¤ãã¦ããããã説æãããã¨ã¨ããã
ãmain.swiftã
import Foundation let table = ["ABC", "DEF", "GHI", "JKL"] let list = LinkedListCreate() for s in table { // 1 var array: CChar[] = s.cStringUsingEncoding(NSUTF8StringEncoding)! // 2 let size: UInt = UInt(sizeof(CChar) * array.count) // 3 LinkedListAddElement(list, &array, size) } // ... for var itr = LinkedListGetIterator(list); LinkedListHasNext(&itr); { // 4 let c: COpaquePointer = LinkedListNextElement(&itr) // 5 let s: String = String.fromCString(UnsafePointer<CChar>(c)) println(s) } LinkedListRelease(list)
0. Swiftå ã§å®ç¾©ããã¦ããCç¨ã®ãã¼ã¿åä¸è¦§
ã¾ãã大åæã¨ãã¦ãSwiftã®åºæ¬ãã¼ã¿åã¯ããªããã£ãåã§ã¯ãªãããªãã¸ã§ã¯ãåã§ããã
let i = 1
ã¨è¨è¿°ããå ´åãi 㯠Int ã¨ããã¯ã©ã¹ã®ã¤ã³ã¹ã¿ã³ã¹ã«ãªãããã®Intåã¯å½ç¶ãCã®intåã¨åãã§ã¯ãªãããæé»ã®åå¤æã¯ã§ããªãã*1
Cã®intã«ç¸å½ããã®ã¯ãSwiftã§ã¯ CInt ã¨ããåã§ããã
Cã®åã«å¯¾å¿ããSwiftåã¯ã以ä¸ãåç §ãä¸è¦§ã¨ãã¦ã¾ã¨ã¾ã£ã¦ããã
1. StringãCCharé åã«å¤æãã
var array: CChar[] = s.cStringUsingEncoding(NSUTF8StringEncoding)!
ããã§ãããããã¨ã¨ããã®ã¯ããSwiftã®æååãvoid*ãã¤ã³ã¿ã¨ãã¦Cã®é¢æ°ã«æ¸¡ããã¨ãããã¨ã§ããã
ããã§1ã¤æ³¨æç¹ãã©ãããããããcStringUsingEncodingã¡ã½ãããè¿ãã®ã¯ãCStringã§ã¯ãªããCChar? ã§ãã((cStringUsingEncodingã®æ»ãå¤ãCCharé åã§ããã¨ããã®ã¯ãã¡ã½ããåã®å½åãã¹ããè¿ãåãééã£ã¦ãããããªãã®ããã¨ããæããcCharArrayUsingEncodingãªãã°ç´å¾ãããã®ã ããã¡ãªã¿ã«ãCChar 㨠CString ã®éã§ã®æé»åå¤æã¯ã§ããªãã®ã§ããcStringUsingEncodingãè¿ãã¦ããã®ã¯å®ã¯CStringåã§ããããCCharé åã«å¤æãã¦ä»£å ¥ãã¦ãããã¨ããå¯è½æ§ã¯ãªãã))ãä¸æ¹ãNSString#UTF8Stringã¯ãCStringåã§ãããã¨ã«æ³¨æã
StringããNSStringãCStringã«å¤æãããã¨ã¯å®¹æããããããä»åã®ä¾ã§ã¯ãconst char*ã§ã¯ãªããvoid*ã§æ¸¡ãããã«Cã®é¢æ°ãè¨è¨ããã¦ãããCã®é¢æ°ãããããconst char* ãå¼æ°ã¨ãã¦åãåãã®ã§ããã°ã
LinkedListAttachElement(list, s.bridgeToObjectiveC().UTF8String)
ã¨ããã°è¯ãã ãã§ãã£ã¦ããã®é¨åã®3è¡ã¯ã¨ã¦ãç°¡æ½ã«ãªãã
ã¨ãããã©ã£ãããSwiftå ã§ã¯ãconst char* ã void* ã¨ãã¦æ±ãï¼æ¸¡ãï¼ãã¨ã¯ã§ããªããï¼å®ã¯ã§ããããããæ¸ãã¦ããåæ¥ã«ãã®ããæ¹ãå¤æããã®ã§ãå¾ã§è¨è¿°ãããããã§ã¯ããã®ããæ¹ããªããã¨ããä½ã§è©±ãé²ãããï¼
å ã»ã©ãªã³ã¯ããå ¬å¼ããã¥ã¡ã³ãã®ä¸æ®µããä¸ã®æ¹ã«ãSwiftã§ç¨æããã¦ãããCç¨ã®ãã¤ã³ã¿åãæ²è¼ããã¦ãããvoid* ãå¼æ°ã§æ¸¡ãã«ã¯ãSwiftã§ã®åãCMutableVoidPointeråã§ãªããã°ãªããªããããã§ã¯ã2ã¹ãããå¾ã§ãCMutableVoidPointeråãå¾ãããã®åæºåã¨ãã¦ãæååããã£ãããCCharé åã«å¤æãã¦ããã
ããã§ä¸çªæ³¨æããªããã°ãªããªããã¨ãããã¯è¡æ«ã® ! ã§ããã
Swiftã® ! å½ä»¤ã¯ããªãã·ã§ãã«åã®å¤ã nil ã§ãªããã¨ã主張ããã©ãããå¤ããã¨ã«ãããã
ä¸æ¹ãCã®void*ãå³ã¡Swiftã®CMutableVoidPointerã¯ããªãã·ã§ãã«åå¤æ°ã®ã¢ãã¬ã¹ããã®ã¾ã¾ï¼ãã®ã¾ã¾ã¨ãã£ã¦ããå¤æ°ã®åã« & ãã¤ããå¿
è¦ããããï¼æ¸¡ããã¨ãã§ãããããã¯ç½ ã§ããããªãã·ã§ãã«åå¤æ°ã®ã¢ãã¬ã¹ãCã®é¢æ°ã«ãã¤ã³ã¿ã¨ãã¦æ¸¡ããå ´åããã®ãã¤ã³ã¿ã®åç
§å¤ãå¾ã®å¤ã¯ãNULLã§ãã*2ãããã¦ãCMutableVoidPointerã¯ããªãã·ã§ãã«åã®ã¢ãã¬ã¹ãåãåããã¨ã許容ãããã¤ã¾ãããã®è¡ã®è¡æ«ã« ! ãä»ããã«ãåæ¨è«ã使ã£ã¦ãCChar[]? åã¨ããå ´åããã®ã³ã¼ãã¯ã³ã³ãã¤ã«ã¯éããã®ã®ããã¾ãåããªãã¨ããçµæã«ãªããåã®è¨äºã§ãæ
£ããã¾ã§åæ¨è«ãããªãæ¹ãããããããã¨æ¸ããã®ã¯ãããããã¨ããã§ã¯ã¾ãå¯è½æ§ãããããã§ãã£ãã
2. Cã®å¼æ°ãunsigned intã§ããå ´åã¯ãSwiftããã¯CUnsignedIntããUIntã§æ¸¡ã
let size: UInt = UInt(sizeof(CChar) * array.count)
Intã§ã¯ãã¡ã
Int â CInt â int
UInt â CUnsignedInt â unsigned int
ã®å¤æã¯èªåã§ãã£ã¦ãããã®ã§ãã¤ã¾ããCã®å¼æ°ãunsigned intã§ããã°ãSwiftããUIntã®å¤æ°ããã®ã¾ã¾æ¸¡ããã¨ãã§ãããå³å¯ã«ã¯ãä»åã®ã³ã³ãã¤ã«ç°å¢ã§ã¯ãsize_tã¯unsigned longã§ããããSwiftããã¯UIntã§æ¸¡ãã¦åé¡ãªãã
ãã®è¡ã®ã
sizeof(CChar) * array.count
ã®é¨åã¯ãIntåã¨Intåã®ä¹ç®ã§ãããçµæãIntåã§ãããã
UInt(sizeof(CChar) * array.count)
ã®é¨åã§ãUIntãªãã¸ã§ã¯ããçæããã®éã«åæåãã©ã¡ã¼ã¿ã¨ãã¦Intå¤ãä¸ãã¦ããã¨ãããã¨ã«ãªãã®ã§ãæçµçã«å®æ°sizeã«å ¥ãå¤ã¯UIntãªãã¸ã§ã¯ãã§ããã
è¡çªå·2ã®è¡ã¯ã次ã®è¡ã¨ãããã¦ã以ä¸ã®ããã«æ¸ããã¨ãã§ããã
let size = sizeof(CChar) * array.count // ãã®æç¹ã§ã¯å®æ°sizeã¯Intå LinkedListAddElement(list, &array, UInt(size)) // 渡ãã¨ãã«UIntåãå¥éçæ
2è¡ãã¾ã¨ãã¦ã
LinkedListAddElement(list, &array, UInt(sizeof(CChar) * array.count))
ã¨ãã¦ãOK
ããã«ã以ä¸ã®ããã«æåããCUnsignedLongã¨ãã¦è¨ç®ããããã¨ãã§ããã
let size: CUnsignedLong = sizeof(CChar).bridgeToObjectiveC().unsignedLongValue * array.count.bridgeToObjectiveC().unsignedLongValue LinkedListAddElement(list, &array, size) // åãåãå´ãsize_tåãªã®ã§ãCUnsignedLongããã®ã¾ã¾æ¸¡ãã
ããããªãããObjective-Cããªãã¸ããã¾ããªãã§ãç´æ¥IntããCIntã«å¤æãããããªãã¨ã¯ã§ããªãã®ã ãããã»ã»ã»ãç§ãç¥ããªãã ãã§ãä½ãããæ¹ãããã®ãããããªãã
3. SwiftããCã®é¢æ°ã«ãã¤ã³ã¿ã渡ãã«ã¯ã&variable
LinkedListAddElement(list, &array, size)
æºåãæ´ã£ãã®ã§ãããã§ããããCã®é¢æ°ãå¼ã³åºãã¦ããã
ãã®ããæ¹ã¯Cã§å¤æ°ã®ã¢ãã¬ã¹ã渡ãã¨ãã¨ä¼¼ã¦ããã®ã§ãããããããé åå¤æ°ã &array ã§æ¸¡ãç¹ã ã注æã
ãªã³ã¯ããå ¬å¼ããã¥ã¡ã³ãã®
You can call it in any of the following ways:
ã®ãããã«ããã¤ã³ã¿æ¸¡ãã®å ·ä½ä¾ã®ä¸è¦§ãæ²è¼ããã¦ããã
ãã¦ãããã§Cé¢æ°ã«æ¸¡ãã¦ããå¼æ°arrayã¯ãCChar[] åã§ãããã&ãã¤ãã¦æ¸¡ãã¦ããã®ã§ãCMutableVoidPointerã¨ãã¦æ¸¡ãã¦ãããã¨ã«ãªããSwiftå¤æ°ï¼varã§å®ç¾©ãããã®ï¼ã« & ãã¤ããã°ããªãã§ãCãªãã¡ããPointerã¨ãã¦åç §å¯è½ã£ã½ããã ããletã¨ãã¦å®ç¾©ããå®æ°ããã¤ã³ã¿ã§åç §ãããã¨ã¯ã§ããªãã
ä»åã¯void*ã¨ãã¦æ¸¡ãããã®ã§ãCMutableVoidPointerã¨ãããªãã§ãããã®åã使ã£ã¦ãã¾ã£ã¦ãããããã¨ãã°ãconst int* ã使ãããã¨ãã¯ãCConstPointer
ã¡ãªã¿ã«ãå¤æ°listã¯ããã§ã«ãã¤ã³ã¿åï¼æ£ç¢ºã«ã¯UnsafePointer
4. Cé¢æ°ããè¿å´ãããvoid*ãã¤ã³ã¿ã¯ãSwiftã§ã¯COpaquePointerã¨ãã¦åãåã
let c: COpaquePointer = LinkedListNextElement(&itr)
å¼æ°ã§ void* ã渡ãã¨ãã¯CMutableVoidPointeråã¨ããããæ»ãå¤ã void* ã§åãåãã«ã¯COpaquePointeråã¨ããããã ã*3ã
var p: COpaquePointer = nil var m: CMutableVoidPointer = nil p = m // NG m = p // OK
ã¨ãããã¨ãããCMutableVoidPointerã¯ãCOpaquePointerã許容ã§ãããããªã®ã§ãCããã®void*æ»ãå¤ãCMutableVoidPointerã§åããã¨ãã§ããã
ä»å㯠void* ãåç
§ãã¦ããã®ã§ãã®ããã«ãã¦ãããããã¤ã³ã¿ã®åã決ã¾ã£ã¦ããã®ã§ããã°ãUnsafePointer
5. CStringããStringãçæãã
let s: String = String.fromCString(UnsafePointer<CChar>(c))
String.fromCStringã¡ã½ããã®å¼æ°ã¯ããã¡ããCStringåã§ãããã¨æããã*4ãå®ã¯ãSwiftã®åºç¤ã¯ã©ã¹ããã¨ãã°Stringã¯ã©ã¹ã®å ¬å¼ã®ã¯ã©ã¹ãªãã¡ã¬ã³ã¹ã®ãããªãã®ãè¦å½ãããªãããã£ããã©ãã«ããã®ããã¼ãã²ãã£ã¨ãã¦ãã¾ã Betaã ããä»å¾å¤æ´ãããããããªããã¨ãããã¨ã§ãã¾ã å ¬éããã¦ããªãã®ãããã
ããã¯åãªãç§ã®äºæ³ã ããfromCStringã¯ãå¼æ°ã¨ãã¦UnsafePointer
ããã¦ãCOpaquePointerãUnsafePointer
æ
å ±ä¸è¶³ã®ããã確ããªãã¨ãè¨ããã«ç³ã訳ãªãããã¨ããããç§ã®ç°å¢ã§è©¦ããã¨ããããã®è¡ã®ã³ã¼ãã§æ£ããvoid*ãã¤ã³ã¿ããStringãªãã¸ã§ã¯ãã¸ã®å¤æãã§ããã
èæï¼
ã1. StringãCCharé åã«å¤æãããã®ã¨ããã§ããCStringãCMutableVoidPointerã«å¤æãããã¨ã¯ã§ããªããã¨ãããããªãã¨ãæ¸ãããããã®åã®è¨äºã«ãããæ¸ããã
以ä¸ã¯ããããè¯ãããæ¹ãªã®ãã©ããã¯ããããªããããä¸å¿ãããã£ããåãããã¨ããã¬ãã«ã®æ å ±ã§ããã
ãæªããã³ã¼ãï¼æ³¨æï¼ã
import Foundation let table = ["ABC", "DEF", "GHI", "JKL"] let list = LinkedListCreate() for s in table { // ãã¤ã³ã¿ã®å 容ãCé¢æ°å ã§ã³ãã¼ããã®ã§ã¯ãªãããã®ã¾ã¾æãããããã«å¤æ´ LinkedListAttachElement(list, reinterpretCast(s.bridgeToObjectiveC().UTF8String) as UnsafePointer<CChar>) } // ... for var itr = LinkedListGetIterator(list); LinkedListHasNext(&itr); { let c: COpaquePointer = LinkedListNextElement(&itr) let s: String = String.fromCString(UnsafePointer<CChar>(c)) println(s) } // Cé¢æ°å ã§åç §ãã¦ããå ¨ãã¤ã³ã¿ã®ææ権ãå¥å¥ª LinkedListDetachAllElements(list) LinkedListRelease(list)
ããã«ã¦ãString â CString â UnsafePointer
reinterpretCastã¨ããé¢æ°èªä½ãAppleã®å ¬å¼ããè¦ã¤ããæ å ±ã§ã¯ãªãã®ã§ããã®é¢æ°ã®åå¨ãç¨éã«ã¤ãã¦ã¯ãç¾æç¹ã§ã¯ãã¾ãä¿¡ç¨ããªãã§ããã ãããã
ååããæ³åããã«ããå解éãã£ã¹ãããªã®ã§ããããããµã¤ãºãåãéãããããããã¤ã³ã¿åã«å¤æã§ããã®ã§ã¯ãªãã ãããã
ä¸è¨ã®ãæªãããã³ã¼ãã¯ãåé ã§æ示ããã³ã¼ãã®å 容ã¨å°ãç°ãªããcStringUsingEncodingã«ãã£ã¦CCharé åãçæããå ´åãããã¯æååã®ä¸æçãªã³ãã¼ã¨ãã¦ã®é åã¨ãªãããUTF8Stringã§åå¾ããCStringã¯ãæååãã¤ã³ã¿ãã®ãã®ãåå¾ã§ãã¦ããããã«è¦ããã
ãããããCé¢æ°å ã§ããã¤ã³ã¿ã®åç §å ã®ãã¼ã¿ãã³ãã¼ãããã¨ããå¦çããããã¤ã³ã¿ããã®ã¾ã¾ä¿æï¼å³ã¡å ±æï¼ãããã¨ããå¦çã«å¤ãã¦ãããSwiftã¨Cã§åããã¤ã³ã¿ãå ±æããããã ãããããã ãèãã¦ãå°ã å±éºãªé¦ããæ¼ã£ã¦ãããããããããä»æ§ã¨ãã¦æ£ããæåã ã¨ç¢ºä¿¡ãæã¦ãããã«ãªãã°ãæååãã³ãã¼ãããããå¹çè¯ãå¦çã§ããå¯è½æ§ããããã«ã§ã¦ããã®ã§ãä»å¾ããå°ã詳ãã調ã¹ã¦ã¿ããã¨ããã ã
ã¨ããã§ãC++ã«ãreinterpret_castã¨ããå½ä»¤æããããã以åç§ãããç¨æããã¦ãã ãã使ã£ã¦ããã°ããã ãï¼ãã¨è¨ã£ãããC++ã®æèè ã«ããäºææ§ãã©ãã§ããã§ããã¾ãè¯ãä½æ³ãããªãããããã¨ããã¨æããããã¨ããããç§ã«ã¯æªã ã«ãreinterpret_castãã©ãããã¨ãã«ã©ã使ãã°è¯ãã®ãããã¾ãã¡ç解ã§ãã¦ããªãã
ã¾ãããããã«ãããæ·±ãç解ãä¼´ããã«ç¡çç¢çãã¤ã³ã¿ããã£ã¹ããããããªãã¨ã¯å±éºãªã®ã§ãããã¦ãããæ¹ãè¯ãã ããã
ãã¦ãä»åãé·ããªã£ãã
Swiftã¨Cã¨ã®éã§ã®ãã¼ã¿æ¸¡ãã§ãããæ°æ¥ç§ãã¯ã¾ã£ãå 容ã¯ã ããããããªã¨ããã ã
ãããã以ä¸ã¯å ¬å¼ããã¥ã¡ã³ãã«ãã詳ãã解説ãªãã§ã¯æ¦ãããã«ãªãã
ãã¨ã¯åè ãã¡ã«ä»»ããã»ã»ã»
ç§ã¯ãã£ã¨ã¬ããå ´æã«æ»ã£ã¦ãSwiftã®åºç¤ææ³ã®å¦ç¿ã§ããããã¨ã«ããã
ã§ã¯ãããã°ã ã
*1:ãã ãããã¯ãSwiftå ã§æé»å¤æãã§ããªãã¨ãã話ã§ãã£ã¦ãå¾è¿°ããããã«ãCã®é¢æ°ã®å¼æ°ã¨ãã¦Swiftå¤æ°ã渡ãã¨ãã«ã¯ãSwiftã®IntããCã®intã¸ã®èªåå¤æã¯ãã£ã¦ãããã
*2:ããã¯å®éã«ãã£ã¦ã¿ãããããªã£ããã¨ãããã¨ã§ãã£ã¦ãä»æ§ã¨ãã¦æ¬å½ã«ãããªãã·ã§ãã«åã®ã¢ãã¬ã¹ãCã«ãã¤ã³ã¿ã¨ãã¦æ¸¡ãããNULLãæããã¤ã³ã¿ã«ãªããã¨ãããã¨ãªã®ãã©ããã¯ãç¾æç¹ã§ã¯ç§ã«ã¯ããããªãã
*3:CMutableVoidPointerã¨COpaquePointerã®éã«ã©ãããéããããã®ãã¯ä»ã®ã¨ããããããã£ã¦ããªãããreinterpretCastã§ãCString â COpaquePointerã¯åããããCString â CMutableVoidPointerã¯å®è¡æã«è½ã¡ãããµã¤ãºãéãã¨ã®ãã¨ã
*4:ãã¡ãããCStringå¤ã渡ããå ´åããã¡ãã¨åä½ããã