Type conversion issue from 'UnsafeMutableRawPointer' to UnsafeMutablePointer<Int32>

Hi, I am new to Swift language.

In my C++ application, I able to convert 'void *' to 'int * 'as below. Here, 'request' type is 'void *' type.
Code Block
int *ret = request;

I am trying to do same thing in Swift also. Here 'request' type is 'UnsafeMutableRawPointer' But I am facing with error

"Cannot convert value of type 'UnsafeMutableRawPointer' to specified type 'UnsafeMutablePointer<Int32>'"

Code Block
let ret: UnsafeMutablePointer<Int32> = request

Any one please help to convert from UnsafeMutableRawPointer type to UnsafeMutablePointer<Int32>.

Accepted Reply

You should have included the C++ code in your initial post.

The best methods to work with Swift pointers are different depending on the context.
You have made me spend some wasted time by hiding very important parts.


In your C++ code, the return type is int, NOT a pointer.
It returns an int value by dereferencing the pointer ret, as shown in return *ret;. You know what * means in C++.

The Swift equivalent to your C++ code would look like this:
Code Block
func test(type: test_type, request: UnsafeMutableRawPointer, request_len: size_t) -> Int32 {
var size: Int = request_len
var mib: [Int32] = [0, 0, 0, 0, 0]
let val: Int32 = sysctl(&mib, 5, request, &size, nil, 0)
if val == 0 {
return request.load(as: Int32.self)
} else if errno == EISDIR || errno == ENOENT {
return 0
}
return -1
}



I am very curious why test in this thread is different than the test in another post of yours.
Hope you would not waste my time any more.

Replies

Here 'request' type is 'UnsafeMutableRawPointer' 

Are you sure ?
How is request defined ?
Isn't it
Code Block
request: UnsafeMutablePointer<request_info_t>

Just write
Code Block
let ret = request

with request defined before as UnsafeMutablePointer<requestinfot>
When you have an UnsafeMutableRawPointer and want to convert it to a typed-pointer like UnsafeMutablePointer<Int32>,
you need to choose one of the two methods of UnsafeMutableRawPointer:
  • Use assumingMemoryBound(to:) when the pointed region can be assumed as bound to the target type

  • Use bindMemory(to:capacity:) when the pointee is not bound

The concept of bound of Swift pointers is sort of abstract and conceptual, and it depends on each case which one should be used.
But I guess you can use assumingMemoryBound(to:) in your case here.

Code Block
let ret: UnsafeMutablePointer<Int32> = request.assumingMemoryBound(to: Int32.self)


If you can show more context, there may be some better ways.
Thanks for help.

Actually I am trying to port following 'test' API from C++ to Swift.

Here, following 'test' function calls sysctl with void type data in 'request' pointer and sysctl returns the result with same 'request' pointer with int type data.

But i am facing issues with below two lines to port from C++ to Swift.
Code Block
 int *ret = (int *)request;
 return *ret;

C++ function:
Code Block
int test(test_type type, void *request, size_t request_len)
{
  size_t size = request_len;
 int mib[] = {0,0,0,0,0};
   
  if (0 == sysctl(mib, 5, request, &size, NULL, 0)) {
    int *ret = (int *)request;
    return *ret;
  } else if (errno == EISDIR || errno == ENOENT) {
    return 0;
  }
  return -1;
}


Swift function:
Code Block
func test( type: test_type, request: UnsafeMutableRawPointer, request_len: size_t) -> Int32
{
  var size: Int = request_len
  var mib: [Int32] = [0, 0, 0, 0, 0]
  let val: Int32 = sysctl(&mib, 5, request, &size, nil, 0)
  if (val == 0) {
    let ret = request
    return UnsafeMutableIPointer<Int32>ret
  } else if (errno == EISDIR || errno == ENOENT) {
    return 0
  }
  return -1
}

You should have included the C++ code in your initial post.

The best methods to work with Swift pointers are different depending on the context.
You have made me spend some wasted time by hiding very important parts.


In your C++ code, the return type is int, NOT a pointer.
It returns an int value by dereferencing the pointer ret, as shown in return *ret;. You know what * means in C++.

The Swift equivalent to your C++ code would look like this:
Code Block
func test(type: test_type, request: UnsafeMutableRawPointer, request_len: size_t) -> Int32 {
var size: Int = request_len
var mib: [Int32] = [0, 0, 0, 0, 0]
let val: Int32 = sysctl(&mib, 5, request, &size, nil, 0)
if val == 0 {
return request.load(as: Int32.self)
} else if errno == EISDIR || errno == ENOENT {
return 0
}
return -1
}



I am very curious why test in this thread is different than the test in another post of yours.
Hope you would not waste my time any more.
Sorry for inconvenience. I thought that, I can try to do myself on remaining part of function with help of few inputs which was provided in other thread. But I have failed to convert remaining part also.

But you have provided the inputs with great explanation. Thank you very much.

Sorry for inconvenience.

Please do not take my words seriously. I'm not good at representing sort of nuances in English.
It is my pleasure if any of my replies helped solving your issue.