我试图将ObjC stackoverflow答案转换为Swift并失败.看起来我正在通过一个UnsafeMutablePointer
我应该通过的时候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) -> 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'
Jerry.. 31
我有点更新了Airspeed Velocity对最新swift语法(Swift 3,beta 6)的回答,但这是我得到的:
func report_memory() { var info = mach_task_basic_info() let MACH_TASK_BASIC_INFO_COUNT = MemoryLayout.stride/MemoryLayout .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")) } }
希望这很有帮助.
我有点更新了Airspeed Velocity对最新swift语法(Swift 3,beta 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")) } }
希望这很有帮助.
Nate的答案非常好,但您可以通过调整来简化它.
首先,task_basic_info
您可以在堆栈上创建结构,而不是分配/取消分配指针,然后使用withUnsafeMutablePointer
直接获取指针,您可以传入该指针.
func report_memory() { var info = mach_task_basic_info() var count = mach_msg_type_number_t(sizeofValue(info))/4 let kerr: kern_return_t = withUnsafeMutablePointer(&info) { task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), task_info_t($0), &count) } if kerr == KERN_SUCCESS { println("Memory in use (in bytes): \(info.resident_size)") } else { println("Error with task_info(): " + (String.fromCString(mach_error_string(kerr)) ?? "unknown error")) } }
与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位以及你的代码中存在的错误.首先,task_info_out
参数需要是a UnsafeMutablePointer<UInt32>
,但实际上需要指向一个实例mach_task_basic_info
.我们可以通过在调用时创建一个UnsafeMutablePointer<mach_task_basic_info>
并将其包装在另一个 UnsafeMutablePointer
中来解决这个问题- 编译器将使用类型推断来知道我们希望包装指针被子类型化为UInt32
.
其次,当你应该调用时,你正在调用sizeof(mach_task_basic_info_t)
(指向mach_task_basic_info
)sizeinfo(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") }