Search code examples
kotlinkotlin-nativekotlin-multiplatform

Unable to reference kotlinx.cinterop package in Kotlin Multiplatform project


I created a Kotlin Multiplatform project based on the example for iOS and Android (https://kotlinlang.org/docs/tutorials/native/mpp-ios-android.html). Within my iOS target, I am using cinterop to link in a 3rd party Objective-C framework. This is working fine. I am able to reference the framework classes in my Kotlin code within the 'iosMain' source set. However, one of the method calls requires an NSError** parameter. I am attempting to use the following to create this variable in my Kotlin code:

kotlinx.cinterop.NativePlacement.allocPointerTo<kotlinx.cinterop.ObjCObjectVar<platform.Foundation.NSError?>()

I have not been able to find away around the following errors:

> Task :sharedLib:linkMainDebugFrameworkIOS FAILED
src/iosMain/kotlin/Platform.kt:9:50: error: unresolved reference: allocPointerTo
    val error = kotlinx.cinterop.NativePlacement.allocPointerTo<kotlinx.cinterop.ObjCObjectVar<platform.Foundation.NSError?>()
                                                 ^
src/iosMain/kotlin/Platform.kt:9:126: error: no value passed for parameter 'rawPtr'
    val error = kotlinx.cinterop.NativePlacement.allocPointerTo<kotlinx.cinterop.ObjCObjectVar<platform.Foundation.NSError?>()

My understanding is that this package is part of stdlib, which should be added as a dependency automatically. Am I missing a piece of the equation somewhere?

UPDATE

The following is an example of passing an NSError* reference from Kotlin:

memScoped {
    val errorRef = alloc<ObjCObjectVar<NSError?>>()
    someObjCObject.method(errorRef.ptr)
}

Solution

  • kotlinx.cinterop.NativePlacement is an interface name, not a class name. You need an instance of the NativePlacement interface to work. For example memscoped{..} block will work, e.g.

    import kotlinx.cinterop.*
    import platform.Foundation.*
    
    val p = memScoped {    
      allocPointerTo<ObjCObjectVar<NSError?>>()
    }
    

    The memscoped{..} accepts a lambda, inside the lambda the receiver implements the NativePlacement type, so there is no need for a qualifier to call a function on it

    https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver