Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 262
glenstorey Avatar asked Mar 11 '23 22:03

glenstorey


1 Answers

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...

EDIT The problem with CommandLine.unsafeArgv is fixed in iOS 12 / Xcode 10, so it may be that this problem is fixed too.

like image 198
matt Avatar answered Apr 26 '23 10:04

matt