2016-10-19 12 views
0

Swiftでは、C関数を呼び出すSwift文字列は、パラメータとして渡されたときにCStringに自動強制変換されます。しかし、私はCの構造体またはグローバルを記入するときに同じ動作をしません。C変数へのスウィート文字列リテラルの割り当て

strlen(swiftString)      //Works! 
CGlobalStruct.stringPtr = swiftString //Doesn't work! 

まず、両方が「const * char」である場合、動作が異なるのはなぜですか。次に、C Structsを記入する最もクリーンな方法は何ですか?

答えて

4

スウィフトStringは、引数として UnsafePointer<Int8>パラメータを引数として渡すことができます。コンパイラは、Swift文字列 の一時的な表現を、NULで終了するシーケンスcharとして生成し、その文字列を に渡します。表現とポインタは、関数呼び出し中にのみ有効なです。グローバルC文字列ポインタを割り当てるとき

strlen(swiftString) 

で何が起こるかであるは、あなたのアカウントにこのポインタの 寿命を取らなければなりません。 1つの可能性は、C文字列表現へのポインタがクロージャに渡される

let swiftString = "Hello world" 

swiftString.withCString { 
    CGlobalStruct.stringPtr = $0 

    // Pointer valid inside this closure ... 
} 
// Pointer not valid anymore ... 

です。 このポインタは、クロージャの実行中にのみ有効です。

guard let cStringPtr = strdup(swiftString) else { 
    fatalError("strdup failed") 
} 
CGlobalStruct.stringPtr = UnsafePointer(cStringPtr) 

// ... 

free(cStringPtr) 
+0

非常に思慮深い応答を:あなたは、メモリに C文字列を割り当てる が、その後、あなたが最終的にそのメモリを解放する責任がある可能性があり、より長い寿命の使用方法については

。 swiftからcへの橋渡しは、ほとんどの場所でかなり良いですが、これがCの構造体に素早い文字列リテラルを割り当てるのと同じくらい良い場合、それはグロス(曖昧ではない)のようなものです。 CGlobalStruct.integer = 45 –

+0

@TroyHarveyのような他のタイプのブリッジングのシンプルさと比較してください。@TroyHarvey:整数は「シンプルな」タイプであり、CとSwiftのメモリ表現は同じです。 Swift Stringは、バイト(純粋なASCII文字列の場合)またはUTF-16コード単位を保持できるいくつかのバッキングストアへの不透明ポインタを持つ構造体で、Swiftによってメモリ管理されますが、C文字列はNULで終了する文字列です。それらの間には単純なブリッジはありません。 –

関連する問題