JetBrains / kotlin-native

Kotlin/Native infrastructure
Apache License 2.0
7.02k stars 566 forks source link

platform.Foundation can't implement closure in Kotlin without crashing #1279

Closed argallo closed 6 years ago

argallo commented 6 years ago
import platform.Foundation.*
import platform.UIKit.*

open class Request {

    fun testing() {
        val url = NSURL.URLWithString(URLString = "https://www.github.com")
        val completion: (NSData?, NSURLResponse?, NSError?) -> Unit = { data, response, error ->
            print("Hello")
        }
        if(url != null) {
            val task = NSURLSession.sharedSession.dataTaskWithURL(url = url, completionHandler = completion)

            task.resume()
        }
    }

}

I've written some kotlin native code and have it compile to a framework for iOS. Everything is working fine until I tried to implement dataTaskWithURL which has a completion handler. I implement the handler but when I run xcode I crash although it's still able to print "hello" to the console.

screen shot 2018-01-31 at 11 23 40 am

Anyone know why this might be happening?

msink commented 6 years ago

https://github.com/JetBrains/kotlin-native/blob/master/INTEROP.md#callbacks

argallo commented 6 years ago

@msink What should I be wrapping here? The completionHandler or dataTaskWithUrl?

    fun request() {
        val url = NSURL.URLWithString(URLString = "https://www.github.com")
        val completion: (NSData?, NSURLResponse?, NSError?) -> Unit = { data, response, error ->
            print("HI")
        }

        if(url != null) {
            val task = NSURLSession.sharedSession.dataTaskWithURL(url, staticCFunction(completion))
            task.resume()
        }
    }

This gives me a error: type inference failed. Expected type mismatch: inferred type is CPointer<CFunction<(NSData?, NSURLResponse?, NSError?) -> Unit>> but (NSData?, NSURLResponse?, NSError?) -> Unit was expected

SvyatoslavScherbina commented 6 years ago

@argallo Kotlin/Native has some special rules restricting cross-thread object passing. E.g. see: https://github.com/JetBrains/kotlin-native/blob/master/runtime/src/main/kotlin/konan/worker/ObjectTransfer.kt#L22

And in your case callback seems to be called from another thread. Please see this code as the example of using NSURLSession within the single thread: https://github.com/JetBrains/kotlinconf-spinner/blob/master/kotlin-native/samples/fullstack/clients/ios/src/main/kotlin/platformUtils.kt#L72

argallo commented 6 years ago

Thanks works great!

par128 commented 4 years ago

The link was broken, fixing. Thank you for the help, @SvyatoslavScherbina https://github.com/Kotlin/kotlinconf-spinner/blob/master/clients/ios/src/iosMain/kotlin/platformUtils.kt

SvyatoslavScherbina commented 4 years ago

Please note that this code may be obsolete. Kotlin/Native is moving fast.

Consider using ktor if you need to make HTTP requests.

par128 commented 4 years ago

@SvyatoslavScherbina we have evaluated ktor. It adds up 1.7 Megabytes to .apk on Android. Too much for our app. But we just need to get json from the server. So I was looking for a compact solution.

e5l commented 4 years ago

Hi @par128, are you using kotlinx.coroutines separately or only with ktor?

par128 commented 4 years ago

Hi, @e5l Leonid! When I was taking the measurements we didn't use coroutines separately. So they probably were included in these 1.7 MB. Now we use them separately. Do you think I should measure once again? How much do you estimate the size of ktor adds up to an Android app?

e5l commented 4 years ago

We didn't measure ktor, but there was a problem with coroutines. I try to investigate, it looks like we should tune the proguard file.