MACH_TASK_BASIC_INFO的Swift指针问题

 mobiledu2502852753 发布于 2022-12-04 15:37

我试图将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"))
    }
}

希望这很有帮助.

3 个回答
  • 我有点更新了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"))
        }
    }
    

    希望这很有帮助.

    2022-12-11 02:13 回答
  • 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"))
        }
    }
    

    2022-12-11 02:57 回答
  • 与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")
    }
    

    2022-12-11 02:57 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有