2015-04-06 14 views
5

我正試圖與來自Swift的舊C終端應用程序進行交互。我已經成功集成了源代碼並將C的頭文件橋接到了Swift中。代碼編譯並從Xcode 6.3 beta運行。我已經改名爲終端應用程序的主入口點:如何將一個Swift字符串數組傳遞給一個帶有char **參數的C函數

int initialize(int argc, char **argv); 

儘管如此,我掙扎着從斯威夫特的參數傳遞給該C函數。我的挑戰是以正確的格式轉換參數。從斯威夫特典型的輸入將如下所示:

let args = ["-c", "1.2.3.4", "-p", "8000"] 

我試過用「cStringUsingEncoding(NSUTF8StringEncoding)」和「withUnsafePointer」搞亂,但至今沒有運氣。任何幫助是極大的讚賞!

+0

標題可以是「更好」的提問題是C函數調用中的char **參數。 – 2017-03-24 21:38:35

回答

6

C函數

int initialize(int argc, char **argv); 

被映射到快速作爲

func initialize(argc: Int32, argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> Int32 

這是一個可能的解決方案:

let args = ["-c", "1.2.3.4", "-p", "8000"] 

// Create [UnsafeMutablePointer<Int8>]: 
var cargs = args.map { strdup($0) } 
// Call C function: 
let result = initialize(Int32(args.count), &cargs) 
// Free the duplicated strings: 
for ptr in cargs { free(ptr) } 

它使用的事實,在strdup($0) 迅串$0會自動轉換爲C字符串, ,如String value to UnsafePointer<UInt8> function parameter behavior中所述。

+0

謝謝,作品像魅力。對於其他人試圖做類似的事情,我應該補充一點,C傳遞從索引1開始而不是0的參數向量。我更新了我的參數:let args = [「」,「-c」,「1.2.3.4」,「 -p「,」8000「]。 – Mark 2015-04-06 15:27:09

+0

如果我有一個命令行遊戲,你認爲可以運行它並將參數傳遞給它,並將它的stdout提取到文本區域,例如swift?還是我必須使用它的功能來完成整個遊戲? @Mark – MasterWizard 2015-12-14 21:51:13

+0

@AhmedNassar:就我所知,您無法在iOS中運行外部程序。 – 2015-12-14 21:55:24

0

大廈馬丁的回答,如果你發現自己做這個有很多,你可以換的DUP /免費部分爲功能相似的風格String.withCString

import Darwin 

func withCStrings 
    <R, S: SequenceType where S.Generator.Element == String> 
    (strings: S, @noescape body: (UnsafeBufferPointer<UnsafeMutablePointer<Int8>>) -> R) 
    -> R { 

    let cstrings = map(strings) { strdup($0) } + [nil] 

    let result = cstrings.withUnsafeBufferPointer(body) 

    for ptr in cstrings { free(ptr) } 

    return result 
} 

let execvargs = ["/usr/bin/say"] + dropFirst(Process.arguments) 

let execvresult = withCStrings(execvargs) { 
    execv($0[0], $0.baseAddress) 
} 
相關問題