Passing Data to a f(void *) function


(Martin R) #1

I have a C function

    void myfunc(const void *ptr);
    
which is imported to Swift as

    func myfunc(_ ptr: UnsafeRawPointer!)
    
This compiles and runs without problems:

    let data = Data(bytes: [1, 2, 3, 4])
    data.withUnsafeBytes { (ptr) in myfunc(ptr) } // (A)

and the type of `ptr` is inferred as `UnsafePointer<Void>`. But adding an explicit type
annotation produces a compiler warning:

    data.withUnsafeBytes { (ptr: UnsafePointer<Void>) in myfunc(ptr) } // (B)
    // warning: UnsafePointer<Void> has been replaced by UnsafeRawPointer
    
which is understandable in the view of "SE-0107 UnsafeRawPointer API".

The "Fix-it" replaces `UnsafePointer<Void>` by `UnsafeRawPointer`, and that does not
compile anymore:

    data.withUnsafeBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) } // (C)
    // error: cannot convert value of type 'Void' to closure result type '_'

because there is no `withUnsafeBytes()` method taking a `(UnsafeRawPointer)->ResultType`
closure.

My questions are:

1. Why are (A) and (B) treated differently?

2. Is (A) "legal", or should one use some non-void pointer

    data.withUnsafeBytes { (ptr: UnsafePointer<Int8>) in myfunc(ptr) } // (D)
    
   (which feels wrong to me because it is converted back to a void pointer when
   calling the function).

3. Or should there be a `withUnsafeRawPointer()` method which makes (C) compile as

      data.withUnsafeRawBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) }

   This would also allow to access the data at byte offsets more easily, e.g.

       data.withUnsafeRawBytes { ptr in
           let u16 = ptr.load(fromByteOffset: 4, as: UInt16.self)
       }
    
   Does that makes sense?

Regards, Martin


(Daniel Dunbar) #2

I have a C function

   void myfunc(const void *ptr);

which is imported to Swift as

   func myfunc(_ ptr: UnsafeRawPointer!)

This compiles and runs without problems:

   let data = Data(bytes: [1, 2, 3, 4])
   data.withUnsafeBytes { (ptr) in myfunc(ptr) } // (A)

and the type of `ptr` is inferred as `UnsafePointer<Void>`. But adding an explicit type
annotation produces a compiler warning:

How do you know the inferred type is `UnsafePointer<Void>`? I think it is more likely it is `UnsafePointer<UInt8>`, and the following compiles:

let data = Data(bytes: [1, 2, 3, 4])
data.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) in
    myfunc(ptr)
}

- Daniel

···

On Jun 30, 2017, at 7:40 AM, Martin R via swift-users <swift-users@swift.org> wrote:

   data.withUnsafeBytes { (ptr: UnsafePointer<Void>) in myfunc(ptr) } // (B)
   // warning: UnsafePointer<Void> has been replaced by UnsafeRawPointer

which is understandable in the view of "SE-0107 UnsafeRawPointer API".

The "Fix-it" replaces `UnsafePointer<Void>` by `UnsafeRawPointer`, and that does not
compile anymore:

   data.withUnsafeBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) } // (C)
   // error: cannot convert value of type 'Void' to closure result type '_'

because there is no `withUnsafeBytes()` method taking a `(UnsafeRawPointer)->ResultType`
closure.

My questions are:

1. Why are (A) and (B) treated differently?

2. Is (A) "legal", or should one use some non-void pointer

   data.withUnsafeBytes { (ptr: UnsafePointer<Int8>) in myfunc(ptr) } // (D)

  (which feels wrong to me because it is converted back to a void pointer when
  calling the function).

3. Or should there be a `withUnsafeRawPointer()` method which makes (C) compile as

     data.withUnsafeRawBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) }

  This would also allow to access the data at byte offsets more easily, e.g.

      data.withUnsafeRawBytes { ptr in
          let u16 = ptr.load(fromByteOffset: 4, as: UInt16.self)
      }

  Does that makes sense?

Regards, Martin

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Joe Groff) #3

This is a bug. The Data API ought to be using UnsafeRawPointer here.

-Joe

···

On Jun 30, 2017, at 7:40 AM, Martin R via swift-users <swift-users@swift.org> wrote:

I have a C function

   void myfunc(const void *ptr);

which is imported to Swift as

   func myfunc(_ ptr: UnsafeRawPointer!)

This compiles and runs without problems:

   let data = Data(bytes: [1, 2, 3, 4])
   data.withUnsafeBytes { (ptr) in myfunc(ptr) } // (A)

and the type of `ptr` is inferred as `UnsafePointer<Void>`. But adding an explicit type
annotation produces a compiler warning:

   data.withUnsafeBytes { (ptr: UnsafePointer<Void>) in myfunc(ptr) } // (B)
   // warning: UnsafePointer<Void> has been replaced by UnsafeRawPointer

which is understandable in the view of "SE-0107 UnsafeRawPointer API".

The "Fix-it" replaces `UnsafePointer<Void>` by `UnsafeRawPointer`, and that does not
compile anymore:

   data.withUnsafeBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) } // (C)
   // error: cannot convert value of type 'Void' to closure result type '_'

because there is no `withUnsafeBytes()` method taking a `(UnsafeRawPointer)->ResultType`
closure.


(^) #4

I believe UnsafeRawPointer is a subtype of any UnsafePointer<T> type, so
UnsafePointer<T>’s are always implicitly convertible to UnsafeRawPointers.
So even the following compiles:

import Foundation

func f(_ a:UnsafeRawPointer)
{

}

let data = Data(bytes: [1, 2, 3, 4])
data.withUnsafeBytes{ (ptr:UnsafePointer<Range<Int>>) in f(ptr) }

So annotate ptr with its actual type, and it should just work.

···

On Fri, Jun 30, 2017 at 10:57 AM, Daniel Dunbar via swift-users < swift-users@swift.org> wrote:

> On Jun 30, 2017, at 7:40 AM, Martin R via swift-users < > swift-users@swift.org> wrote:
>
> I have a C function
>
> void myfunc(const void *ptr);
>
> which is imported to Swift as
>
> func myfunc(_ ptr: UnsafeRawPointer!)
>
> This compiles and runs without problems:
>
> let data = Data(bytes: [1, 2, 3, 4])
> data.withUnsafeBytes { (ptr) in myfunc(ptr) } // (A)
>
> and the type of `ptr` is inferred as `UnsafePointer<Void>`. But adding
an explicit type
> annotation produces a compiler warning:

How do you know the inferred type is `UnsafePointer<Void>`? I think it is
more likely it is `UnsafePointer<UInt8>`, and the following compiles:

let data = Data(bytes: [1, 2, 3, 4])
data.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) in
    myfunc(ptr)
}

- Daniel

>
> data.withUnsafeBytes { (ptr: UnsafePointer<Void>) in myfunc(ptr) } //
(B)
> // warning: UnsafePointer<Void> has been replaced by UnsafeRawPointer
>
> which is understandable in the view of "SE-0107 UnsafeRawPointer API".
>
> The "Fix-it" replaces `UnsafePointer<Void>` by `UnsafeRawPointer`, and
that does not
> compile anymore:
>
> data.withUnsafeBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) } // (C)
> // error: cannot convert value of type 'Void' to closure result type
'_'
>
> because there is no `withUnsafeBytes()` method taking a
`(UnsafeRawPointer)->ResultType`
> closure.
>
>
> My questions are:
>
> 1. Why are (A) and (B) treated differently?
>
> 2. Is (A) "legal", or should one use some non-void pointer
>
> data.withUnsafeBytes { (ptr: UnsafePointer<Int8>) in myfunc(ptr) } //
(D)
>
> (which feels wrong to me because it is converted back to a void
pointer when
> calling the function).
>
> 3. Or should there be a `withUnsafeRawPointer()` method which makes (C)
compile as
>
> data.withUnsafeRawBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) }
>
> This would also allow to access the data at byte offsets more easily,
e.g.
>
> data.withUnsafeRawBytes { ptr in
> let u16 = ptr.load(fromByteOffset: 4, as: UInt16.self)
> }
>
> Does that makes sense?
>
> Regards, Martin
>
>
>
>
>
>
>
>
>
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Martin R) #5

I have a C function

  void myfunc(const void *ptr);

which is imported to Swift as

  func myfunc(_ ptr: UnsafeRawPointer!)

This compiles and runs without problems:

  let data = Data(bytes: [1, 2, 3, 4])
  data.withUnsafeBytes { (ptr) in myfunc(ptr) } // (A)

and the type of `ptr` is inferred as `UnsafePointer<Void>`. But adding an explicit type
annotation produces a compiler warning:

How do you know the inferred type is `UnsafePointer<Void>`? I think it is more likely it is `UnsafePointer<UInt8>`, and the following compiles:

let data = Data(bytes: [1, 2, 3, 4])
data.withUnsafeBytes { (ptr: UnsafePointer<UInt8>) in
   myfunc(ptr)
}

- Daniel

Command-click on "ptr" in "myfunc(ptr)" (or the Quick Help inspector) shows

    let ptr: (UnsafePointer<()>)

···

On 30. Jun 2017, at 16:57, Daniel Dunbar <daniel_dunbar@apple.com> wrote:

On Jun 30, 2017, at 7:40 AM, Martin R via swift-users <swift-users@swift.org> wrote:

  data.withUnsafeBytes { (ptr: UnsafePointer<Void>) in myfunc(ptr) } // (B)
  // warning: UnsafePointer<Void> has been replaced by UnsafeRawPointer

which is understandable in the view of "SE-0107 UnsafeRawPointer API".

The "Fix-it" replaces `UnsafePointer<Void>` by `UnsafeRawPointer`, and that does not
compile anymore:

  data.withUnsafeBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) } // (C)
  // error: cannot convert value of type 'Void' to closure result type '_'

because there is no `withUnsafeBytes()` method taking a `(UnsafeRawPointer)->ResultType`
closure.

My questions are:

1. Why are (A) and (B) treated differently?

2. Is (A) "legal", or should one use some non-void pointer

  data.withUnsafeBytes { (ptr: UnsafePointer<Int8>) in myfunc(ptr) } // (D)

(which feels wrong to me because it is converted back to a void pointer when
calling the function).

3. Or should there be a `withUnsafeRawPointer()` method which makes (C) compile as

    data.withUnsafeRawBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) }

This would also allow to access the data at byte offsets more easily, e.g.

     data.withUnsafeRawBytes { ptr in
         let u16 = ptr.load(fromByteOffset: 4, as: UInt16.self)
     }

Does that makes sense?

Regards, Martin

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Andrew Trick) #6

I was going for UnsafeRawBufferPointer. Here’s a prototype from Sept ‘16:
https://github.com/atrick/swift/commit/796b08fa5635a7d61cbb6bf0718178e0ce326e4f

I created a JIRA to track this and related issues: https://bugs.swift.org/browse/SR-5363

-Andy

···

On Jun 30, 2017, at 9:14 AM, Joe Groff via swift-users <swift-users@swift.org> wrote:

On Jun 30, 2017, at 7:40 AM, Martin R via swift-users <swift-users@swift.org> wrote:

I have a C function

  void myfunc(const void *ptr);

which is imported to Swift as

  func myfunc(_ ptr: UnsafeRawPointer!)

This compiles and runs without problems:

  let data = Data(bytes: [1, 2, 3, 4])
  data.withUnsafeBytes { (ptr) in myfunc(ptr) } // (A)

and the type of `ptr` is inferred as `UnsafePointer<Void>`. But adding an explicit type
annotation produces a compiler warning:

  data.withUnsafeBytes { (ptr: UnsafePointer<Void>) in myfunc(ptr) } // (B)
  // warning: UnsafePointer<Void> has been replaced by UnsafeRawPointer

which is understandable in the view of "SE-0107 UnsafeRawPointer API".

The "Fix-it" replaces `UnsafePointer<Void>` by `UnsafeRawPointer`, and that does not
compile anymore:

  data.withUnsafeBytes { (ptr: UnsafeRawPointer) in myfunc(ptr) } // (C)
  // error: cannot convert value of type 'Void' to closure result type '_'

because there is no `withUnsafeBytes()` method taking a `(UnsafeRawPointer)->ResultType`
closure.

This is a bug. The Data API ought to be using UnsafeRawPointer here.

-Joe