glenstorey glenstorey - 1 month ago 38
Swift Question

UnsafeMutablePointer to expected argument type UnsafeMutablePointer<_> in Swift 3

In the

main.swift
file, we have a call to our receipt checking system (generated by Receigen). In Swift 2,
main.swift
read:

startup(Process.argc, UnsafeMutablePointer<UnsafePointer<Int8>>(Process.unsafeArgv))


After upgrading to Swift 3, I've got as far as:

startup(CommandLine.argc, UnsafeMutablePointer<UnsafePointer<Int8>>(CommandLine.unsafeArgv))


which shows the error:


Cannot convert value of type
UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>
(aka
UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>
) to
expected argument type
UnsafeMutablePointer<_>



Update: Using the linked question so that it reads:

startup(CommandLine.argc, UnsafeMutableRawPointer(CommandLine.unsafeArgv)
.bindMemory(
to: UnsafeMutablePointer<Int8>.self,
capacity: Int(CommandLine.argc)))


Produces:


Cannot convert value of type
UnsafeMutablePointer<Int8>.Type
to
expected argument type
UnsafePointer<Int8>?.Type
(aka
Optional<UnsafePointer<Int8>>.Type
)


Where the compiler is referring to the
to:UnsafeMutablePointer
.

The header for startup looks like:

int startup(int argc, const char * argv[]);


How can I successfully pass the variables to startup in
main.swift
?

Answer

Basically, this is a variant on the problem discussed here:

Xcode 8 beta 6: main.swift won't compile

The problem is that you have an impedance mismatch between the type of CommandLine.unsafeArgv and the type expected by your C function. And you can no longer cast away this mismatch merely by coercing from one mutable pointer type to another. Instead, you have to pivot (as it were) from one type to another by calling bindMemory. And the error message, demanding a Optional<UnsafePointer<Int8>>.Type, tells you what type to pivot to:

    startup(
        CommandLine.argc,
        UnsafeMutableRawPointer(CommandLine.unsafeArgv)
            .bindMemory(
                to: Optional<UnsafePointer<Int8>>.self,
                capacity: Int(CommandLine.argc))
    )

That should allow you to compile. Testing on my machine with a stub of startup, it actually runs. But whether it will run on your machine, and whether it is safe, is anybody's guess! This stuff is undeniably maddening...

Comments