我正在尝试将答案转换为Swift并失败。似乎我正在传递一个UnsafeMutablePointer<mach_msg_type_number_t>应该何时传递一个,inout mach_msg_type_number_t而我似乎无法解决我的问题。据我了解的Swift指针文档(不多),这些应该可以互换。
UnsafeMutablePointer<mach_msg_type_number_t>
inout mach_msg_type_number_t
下面的更多信息。
这是目标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签名是:
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'
与C函数进行交互时,您不能依靠编译器的错误消息-逐个参数地将其分解,然后单击命令直至知道要使用的内容。首先,您遇到的类型是:
task_name_t
UInt32
task_flavor_t
task_info_t
UnsafeMutablePointer<Int32>
UnsafeMutablePointer<UInt32>
kern_return_t
Int32
这里有一个棘手的Swift位以及代码中的一个错误,阻碍了您的发展。首先,task_info_out参数必须为UnsafeMutablePointer<UInt32>,但实际上需要指向的实例mach_task_basic_info。我们可以通过在调用时创建一个UnsafeMutablePointer<mach_task_basic_info>并将其包装在 另一个 包装中来解决此问题UnsafeMutablePointer-编译器将使用类型推断来知道我们希望将包装指针子类型化为UInt32。
task_info_out
mach_task_basic_info
UnsafeMutablePointer<mach_task_basic_info>
UnsafeMutablePointer
其次,您在 应调用时正在调用sizeof(mach_task_basic_info_t)(指向的指针mach_task_basic_info)sizeinfo(mach_task_basic_info),因此字节数最终太少而无法容纳数据结构。
sizeof(mach_task_basic_info_t)
sizeinfo(mach_task_basic_info)
在进一步的研究中,这变得更加复杂。原始代码不正确,size应将其初始化为constant MACH_TASK_BASIC_INFO_COUNT。不幸的是,这是一个宏,而不是简单的常量:
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") }