0

I am trying to convert below code to Swift:

{
    // Set up the variables
    double totalUsedMemory = 0.00;
    mach_port_t host_port;
    mach_msg_type_number_t host_size;
    vm_size_t pagesize;

    // Get the variable values
    host_port = mach_host_self();
    host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
    host_page_size(host_port, &pagesize);

    vm_statistics_data_t vm_stat;

    // Check for any system errors
    if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
        // Error, failed to get Virtual memory info
        return -1;
    }

    // Memory statistics in bytes
    natural_t usedMemory = (natural_t)((vm_stat.active_count +
                            vm_stat.inactive_count +
                            vm_stat.wire_count) * pagesize);
    natural_t allMemory = [self totalMemory];


    return usedMemory;
}

My Swift code is:

{
    // Set up the variables
    var totalUsedMemory: Double = 0.00
    var host_port: mach_port_t
    var host_size: mach_msg_type_number_t
    var pagesize:vm_size_t

    // Get the variable values
     host_port = mach_host_self()

    host_size = mach_msg_type_number_t(MemoryLayout<vm_statistics_data_t>.stride / MemoryLayout<integer_t>.stride)

    //                host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
    host_page_size(host_port, &pagesize);

    var vm_stat: vm_statistics_data_t ;

    // Check for any system errors
    if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
        // Error, failed to get Virtual memory info
        return -1;
    }
    // Memory statistics in bytes
    var usedMemory: Int64  = (Int64)((vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pagesize);

    return usedMemory;
}

I am getting these 2 errors:

**Binary operator '&' cannot be applied to operands of type '(host_info_t).Type' (aka 'UnsafeMutablePointer.Type') and 'vm_statistics_data_t' (aka 'vm_statistics')

in this statement host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size)

And

Binary operator '*' cannot be applied to operands of type 'UInt32' and 'vm_size_t' (aka 'UInt')**

in this statement - var usedMemory: Int64 = (Int64)((vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pagesize);

7
  • You should point out which lines are giving you the errors.
    – rmaddy
    Commented Feb 14, 2018 at 0:31
  • 1
    check the type of pagesize and if it's a UIInt_32 convert it to a UIInt_64. Then the host_statistics() function is all in C pretty much. The & is a pointer and they don't work in swift. Try adding @objc to that part
    – Jake
    Commented Feb 14, 2018 at 0:36
  • Given that the core of that function is the call to host_statistics, and given that the call to host_statistics can't be converted to swift, why bother changing the function? Commented Feb 14, 2018 at 0:45
  • @Jake, I tried by converting pagesize to UInt32 and UInt64 both but no luck. Commented Feb 14, 2018 at 0:51
  • 1
    @Alexander Or make it a throwing function that returns an Int, and throw an error instead of returning -1 or nil. Commented Feb 15, 2018 at 16:25

1 Answer 1

3

Swift is a lot more strict about pointer types than C is, which can make it a real pain to interact with functions like this that expect you to pass pointers to types other than the actual type of the thing you're trying to pass to the function. So I agree with the commenters that you're probably better off leaving this function in (Objective-)C. However, if you absolutely have to convert to Swift, you're probably going to have to do something like this:

// Initialize a blank vm_statistics_data_t
var vm_stat = vm_statistics_data_t()

// Get a raw pointer to vm_stat
let err: kern_return_t = withUnsafeMutableBytes(of: &vm_stat) {
    // Bind the raw buffer to Int32, since that's what host_statistics
    // seems to want a pointer to.
    let boundBuffer = $0.bindMemory(to: Int32.self)

    // Call host_statistics, and return its status out of the closure.
    return host_statistics(host_port, HOST_VM_INFO, boundBuffer.baseAddress, &host_size)
}

// Now take a look at what we got and compare it against KERN_SUCCESS
if err != KERN_SUCCESS {
    // Error, failed to get Virtual memory info
    return -1;
}
5
  • 1
    @user1101733 Just cast the UInt32 to a vm_size_t. Swift requires types in math operations to be the same, unlike C, which is why you're getting that error. Commented Feb 14, 2018 at 0:59
  • -Working :-) I was trying reverse- Was converting vm_size_t to UInt32. Why this was not working? any idea Commented Feb 14, 2018 at 1:19
  • @user1101733 vm_size_t is a typealias to UInt, which has a larger maximum than UInt32. If you do a bunch of add and multiply operations on a UInt32 and the result is larger than what a UInt32 can hold, you'll crash. Commented Feb 14, 2018 at 1:28
  • Yes, It was crashing. Commented Feb 14, 2018 at 3:31
  • I updated the answer to Swift 4.1. Currently this requires the Xcode 9.3 beta, but since Xcode 9.3 will probably be released before too long, this answer is better for posterity, as it's cleaner and doesn't require you to fuss around with MemoryLayout. For a Swift 4.0-compatible version, check the edit history. Commented Feb 15, 2018 at 17:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.