15

ObjC スタックオーバーフローの回答を Swift に変換しようとしていますが、失敗しています。UnsafeMutablePointer<mach_msg_type_number_t>渡す必要があるときに を渡しているように見えますがinout mach_msg_type_number_t、問題を解決できないようです。Swiftポインタのドキュメント(あまりない)について私が理解していることから、これらは交換可能であるはずです..?

詳細は以下をご覧ください。

目的 C は次のとおりです。

struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);

そして、これがSwiftで得た限りです(型チェックを簡単にするために多くの行があります)

let name: task_name_t = mach_task_self_
let flavor: task_flavor_t = task_flavor_t(MACH_TASK_BASIC_INFO)
var info: mach_task_basic_info
var size: mach_msg_type_number_t = UnsignedFixed(sizeof(mach_task_basic_info_t))
let kerr = task_info(name, flavor, info as task_info_t, &size)

task_info署名は次のとおりです。

func task_info(target_task: task_name_t, flavor: task_flavor_t, task_info_out: task_info_t, task_info_outCnt: UnsafeMutablePointer<mach_msg_type_number_t>) -> kern_return_t

最後の行のエラーは次のとおりです。

Cannot convert the expression's type '(@!lvalue task_name_t, task_flavor_t, task_info_t, inout mach_msg_type_number_t)' to type 'kern_return_t'
4

6 に答える 6

40

Airspeed Velocity の回答を最新の Swift 構文 (Swift 3、ベータ 6) に更新するのに少し時間がかかりましたが、ここに私が得たものがあります:

func report_memory() {
    var info = mach_task_basic_info()
    let MACH_TASK_BASIC_INFO_COUNT = MemoryLayout<mach_task_basic_info>.stride/MemoryLayout<natural_t>.stride
    var count = mach_msg_type_number_t(MACH_TASK_BASIC_INFO_COUNT)

    let kerr: kern_return_t = withUnsafeMutablePointer(to: &info) {
        $0.withMemoryRebound(to: integer_t.self, capacity: MACH_TASK_BASIC_INFO_COUNT) {
            task_info(mach_task_self_,
                      task_flavor_t(MACH_TASK_BASIC_INFO),
                      $0,
                      &count)
        }
    }

    if kerr == KERN_SUCCESS {
        print("Memory in use (in bytes): \(info.resident_size)")
    }
    else {
        print("Error with task_info(): " +
            (String(cString: mach_error_string(kerr), encoding: String.Encoding.ascii) ?? "unknown error"))
    }
}

お役に立てば幸いです。

于 2016-08-19T22:46:02.363 に答える
15

C 関数とやり取りするときは、コンパイラのエラー メッセージに頼ることはできません。パラメータごとに分解し、何を扱っているかがわかるまでコマンド クリックします。まず、実行しているタイプは次のとおりです。

  • task_name_t:UInt32
  • task_flavor_t:UInt32
  • task_info_t:UnsafeMutablePointer<Int32>
  • UnsafeMutablePointer<mach_msg_type_number_t>:UnsafeMutablePointer<UInt32>
  • kern_return_t-Int32

Swift のトリッキーなビットが 1 つあります。また、コードのバグがここで邪魔になります。まず、task_info_outパラメータは である必要がありますがUnsafeMutablePointer<UInt32>、実際には のインスタンスを指している必要がありますmach_task_basic_info。これを回避するには、 を作成し、呼び出し時に別のUnsafeMutablePointer<mach_task_basic_info>ラップでラップします。コンパイラは、型推論を使用して、ラップ ポインターを としてサブタイプ化する必要があることを認識します。 UnsafeMutablePointerUInt32

次に、 を呼び出す必要があるときにsizeof(mach_task_basic_info_t)( へのポインタ) を呼び出しているため、データ構造を保持するにはバイト数が少なすぎます。mach_task_basic_infosizeinfo(mach_task_basic_info)

さらなる研究で、これはもう少し複雑になりました。これの元のコードは正しくsizeなく、定数に初期化する必要がありましたMACH_TASK_BASIC_INFO_COUNT。残念ながら、これは単純な定数ではなくマクロです。

#define MACH_TASK_BASIC_INFO_COUNT (sizeof(mach_task_basic_info_data_t) / sizeof(natural_t)) 

Swift はそれらをインポートしないので、自分で再定義する必要があります。これらすべての作業コードは次のとおりです。

// constant
let MACH_TASK_BASIC_INFO_COUNT = (sizeof(mach_task_basic_info_data_t) / sizeof(natural_t))

// prepare parameters
let name   = mach_task_self_
let flavor = task_flavor_t(MACH_TASK_BASIC_INFO)
var size   = mach_msg_type_number_t(MACH_TASK_BASIC_INFO_COUNT)

// allocate pointer to mach_task_basic_info
var infoPointer = UnsafeMutablePointer<mach_task_basic_info>.alloc(1)

// call task_info - note extra UnsafeMutablePointer(...) call
let kerr = task_info(name, flavor, UnsafeMutablePointer(infoPointer), &size)

// get mach_task_basic_info struct out of pointer
let info = infoPointer.move()

// deallocate pointer
infoPointer.dealloc(1)

// check return value for success / failure
if kerr == KERN_SUCCESS {
    println("Memory in use (in bytes): \(info.resident_size)")
} else {
    let errorString = String(CString: mach_error_string(kerr), encoding: NSASCIIStringEncoding)
    println(errorString ?? "Error: couldn't parse error string")
}
于 2014-12-19T04:33:15.723 に答える