2015-04-06 3 views
5

Я пытаюсь взаимодействовать со старым C-терминальным приложением от Swift. Я успешно интегрировал исходный код и перекрыл заголовки от C до Swift. Код компилируется и запускается из бета-версии Xcode 6.3. Я переименовал главную точку входа терминального приложения для:Как передать массив строк Swift функции C с параметром char **

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

Тем не менее, я изо всех сил, чтобы передать аргументы от Swift этой функции C. Моя задача - преобразовать аргументы в правильном формате. Типичный вход от Swift будет выглядеть так:

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

Я пытался баловаться с «cStringUsingEncoding (NSUTF8StringEncoding)» и «withUnsafePointer», но не везло до сих пор. Любая помощь очень ценится!

+0

название может быть «лучше», упоминая что проблема является параметром char ** в вызове функции C. –

ответ

6

Функция С

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

отображается на Swift, как

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

+0

Если у меня есть игра в командной строке, вы думаете, что ее можно запустить и передать ей аргументы, а также вывести его stdout в текстовую область, например, в swift? Или мне нужно делать игру со всех сторон, используя ее функцию? @Mark – MasterWizard

+0

@AhmedNassar: Вы не можете запускать внешние программы в iOS, насколько я знаю. –

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) 
} 
Смежные вопросы