diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt index 6aa8d93ccbc..29ff478aab4 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCImpl.kt @@ -38,7 +38,7 @@ private fun ObjCObjectBase.superInitCheck(superInitCallResult: ObjCObject?) { if (superInitCallResult == null) throw RuntimeException("Super initialization failed") - if (superInitCallResult.rawPtr() != this.rawPtr()) + if (superInitCallResult.objcPtr() != this.objcPtr()) throw UnsupportedOperationException("Super initializer has replaced object") } @@ -46,25 +46,25 @@ private fun ObjCObjectBase.superInitCheck(superInitCallResult: ObjCObject?) { fun Any?.uncheckedCast(): T = @Suppress("UNCHECKED_CAST") (this as T) // TODO: make private @SymbolName("Kotlin_Interop_refFromObjC") -external fun interpretObjCPointerOrNull(rawPtr: NativePtr): T? +external fun interpretObjCPointerOrNull(objcPtr: NativePtr): T? -inline fun interpretObjCPointer(rawPtr: NativePtr): T = interpretObjCPointerOrNull(rawPtr)!! +inline fun interpretObjCPointer(objcPtr: NativePtr): T = interpretObjCPointerOrNull(objcPtr)!! @SymbolName("Kotlin_Interop_refToObjC") -external fun ObjCObject?.rawPtr(): NativePtr +external fun Any?.objcPtr(): NativePtr @SymbolName("Kotlin_Interop_createKotlinObjectHolder") external fun createKotlinObjectHolder(any: Any?): NativePtr -inline fun unwrapKotlinObjectHolder(holder: ObjCObject?): T { - return unwrapKotlinObjectHolderImpl(holder!!.rawPtr()) as T +inline fun unwrapKotlinObjectHolder(holder: Any?): T { + return unwrapKotlinObjectHolderImpl(holder!!.objcPtr()) as T } @PublishedApi @SymbolName("Kotlin_Interop_unwrapKotlinObjectHolder") external internal fun unwrapKotlinObjectHolderImpl(ptr: NativePtr): Any -class ObjCObjectVar(rawPtr: NativePtr) : CVariable(rawPtr) { +class ObjCObjectVar(rawPtr: NativePtr) : CVariable(rawPtr) { companion object : CVariable.Type(pointerSize.toLong(), pointerSize) } @@ -139,9 +139,11 @@ private external fun getObjCClass(): NativePtr // Konan runtme: +@Deprecated("Use plain Kotlin cast of String to NSString", level = DeprecationLevel.WARNING) @SymbolName("Kotlin_Interop_CreateNSStringFromKString") external fun CreateNSStringFromKString(str: String?): NativePtr +@Deprecated("Use plain Kotlin cast of NSString to String", level = DeprecationLevel.WARNING) @SymbolName("Kotlin_Interop_CreateKStringFromNSString") external fun CreateKStringFromNSString(ptr: NativePtr): String? diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCUtils.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCUtils.kt index fac6866b526..536aeb9d62d 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCUtils.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/ObjectiveCUtils.kt @@ -29,11 +29,11 @@ inline fun autoreleasepool(block: () -> R): R { fun ObjCObject.reinterpret() = @Suppress("DEPRECATION") this.uncheckedCast() // TODO: null checks -var ObjCObjectVar.value: T +var ObjCObjectVar.value: T @Suppress("DEPRECATION") get() = interpretObjCPointerOrNull(nativeMemUtils.getNativePtr(this)).uncheckedCast() - set(value) = nativeMemUtils.putNativePtr(this, value.rawPtr()) + set(value) = nativeMemUtils.putNativePtr(this, value.objcPtr()) /** * Makes Kotlin method in Objective-C class accessible through Objective-C dispatch diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt index 2f858ea29f9..227b2bb23fa 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/Varargs.kt @@ -44,7 +44,7 @@ private tailrec fun convertArgument( // If it is fixed argument, then it is not C string because it must have been already converted; // then treat it as NSString. // TODO: handle fixed NSString arguments in the stub instead. - interpretCPointer(CreateNSStringFromKString(argument)) + interpretCPointer(argument.objcPtr()) } else { // It is passed as variadic argument; no type information available, so treat it as C string. argument.cstr.getPointer(additionalPlacement) @@ -93,7 +93,7 @@ private tailrec fun convertArgument( is CEnum -> convertArgument(argument.value, isVariadic, location, additionalPlacement) is ForeignObjCObject -> { - location.reinterpret()[0] = interpretCPointer((argument as ObjCObject).rawPtr()) + location.reinterpret()[0] = interpretCPointer(argument.objcPtr()) FFI_TYPE_KIND_POINTER } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt index ee1cf02d651..2d014893d9e 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/KotlinCodeModel.kt @@ -168,6 +168,12 @@ object KotlinTypes { val string by BuiltInType val any by BuiltInType + val list by CollectionClassifier + val mutableList by CollectionClassifier + val set by CollectionClassifier + val map by CollectionClassifier + + val nativePtr by InteropType val cOpaque by InteropType @@ -198,20 +204,21 @@ object KotlinTypes { val cValue by InteropClassifier - private object BuiltInType { - operator fun getValue(thisRef: KotlinTypes, property: KProperty<*>): KotlinClassifierType = - Classifier.topLevel("kotlin", property.name.capitalize()).type - } - - private object InteropClassifier { + private open class ClassifierAtPackage(val pkg: String) { operator fun getValue(thisRef: KotlinTypes, property: KProperty<*>): Classifier = - Classifier.topLevel("kotlinx.cinterop", property.name.capitalize()) + Classifier.topLevel(pkg, property.name.capitalize()) } - private object InteropType { + private open class TypeAtPackage(val pkg: String) { operator fun getValue(thisRef: KotlinTypes, property: KProperty<*>): KotlinClassifierType = - InteropClassifier.getValue(thisRef, property).type + Classifier.topLevel(pkg, property.name.capitalize()).type } + + private object BuiltInType : TypeAtPackage("kotlin") + private object CollectionClassifier : ClassifierAtPackage("kotlin.collections") + + private object InteropClassifier : ClassifierAtPackage("kotlinx.cinterop") + private object InteropType : TypeAtPackage("kotlinx.cinterop") } abstract class KotlinFile( diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt index d7efb18ed85..d607594e815 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/Mappings.kt @@ -192,7 +192,7 @@ sealed class TypeInfo { } class ObjCPointerInfo(val kotlinType: KotlinType, val type: ObjCPointer) : TypeInfo() { - override fun argToBridged(expr: String) = "$expr.rawPtr()" + override fun argToBridged(expr: String) = "$expr.objcPtr()" override fun argFromBridged(expr: KotlinExpression, scope: KotlinScope, nativeBacked: NativeBacked) = "interpretObjCPointerOrNull<${kotlinType.render(scope)}>($expr)" + @@ -204,20 +204,6 @@ sealed class TypeInfo { override fun constructPointedType(valueType: KotlinType) = KotlinTypes.objCObjectVar.typeWith(valueType) } - class NSString(val type: ObjCPointer) : TypeInfo() { - override fun argToBridged(expr: String) = "CreateNSStringFromKString($expr)" - - override fun argFromBridged(expr: KotlinExpression, scope: KotlinScope, nativeBacked: NativeBacked) = - "CreateKStringFromNSString($expr)" + if (type.isNullable) "" else "!!" - - override val bridgedType: BridgedType - get() = BridgedType.OBJC_POINTER - - override fun constructPointedType(valueType: KotlinType): KotlinClassifierType { - return KotlinTypes.objCStringVarOf.typeWith(valueType) - } - } - class ObjCBlockPointerInfo(val kotlinType: KotlinFunctionType, val type: ObjCBlockPointer) : TypeInfo() { override val bridgedType: BridgedType @@ -487,20 +473,29 @@ internal fun ObjCClass.isNSStringSubclass(): Boolean = this.baseClass?.isNSStrin private fun objCPointerMirror(declarationMapper: DeclarationMapper, type: ObjCPointer): TypeMirror.ByValue { if (type is ObjCObjectPointer && type.def.isNSStringOrSubclass()) { - val info = TypeInfo.NSString(type) - return objCMirror(KotlinTypes.string, info, type.isNullable) + val valueType = KotlinTypes.string + return objCMirror(valueType, TypeInfo.ObjCPointerInfo(valueType, type), type.isNullable) } - val clazz = when (type) { - is ObjCIdType -> type.protocols.firstOrNull()?.let { declarationMapper.getKotlinClassFor(it) } - ?: KotlinTypes.objCObject - is ObjCClassPointer -> KotlinTypes.objCClass - is ObjCObjectPointer -> declarationMapper.getKotlinClassFor(type.def) + val valueType = when (type) { + is ObjCIdType -> { + type.protocols.firstOrNull()?.let { declarationMapper.getKotlinClassFor(it) }?.type + ?: KotlinTypes.any + } + is ObjCClassPointer -> KotlinTypes.objCClass.type + is ObjCObjectPointer -> { + when (type.def.name) { + "NSArray" -> KotlinTypes.list.typeWith(StarProjection) + "NSMutableArray" -> KotlinTypes.mutableList.typeWith(KotlinTypes.any.makeNullable()) + "NSSet" -> KotlinTypes.set.typeWith(StarProjection) + "NSDictionary" -> KotlinTypes.map.typeWith(KotlinTypes.any.makeNullable(), StarProjection) + else -> declarationMapper.getKotlinClassFor(type.def).type + } + } is ObjCInstanceType -> TODO(type.toString()) // Must have already been handled. is ObjCBlockPointer -> return objCBlockPointerMirror(declarationMapper, type) } - val valueType = clazz.type return objCMirror(valueType, TypeInfo.ObjCPointerInfo(valueType, type), type.isNullable) } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt index 60be4a823eb..8c2b41c72fe 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/ObjCStubs.kt @@ -506,11 +506,11 @@ class ObjCPropertyStub( } val result = mutableListOf( "$modifiers$kind $receiver${property.name.asSimpleName()}: $kotlinType", - " get() = ${getterStub.bridgeName}(nativeNullPtr, this.rawPtr())" + " get() = ${getterStub.bridgeName}(nativeNullPtr, this.objcPtr())" ) property.setter?.let { - result.add(" set(value) = ${setterStub!!.bridgeName}(nativeNullPtr, this.rawPtr(), value)") + result.add(" set(value) = ${setterStub!!.bridgeName}(nativeNullPtr, this.objcPtr(), value)") } return result.asSequence() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt index 88e083aa1d2..2f65aa44190 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InteropUtils.kt @@ -166,10 +166,7 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns) { val getObjCClass = packageScope.getContributedFunctions("getObjCClass").single() - val objCObjectRawPtr = packageScope.getContributedFunctions("rawPtr").single { - val extensionReceiverType = it.extensionReceiverParameter?.type - extensionReceiverType != null && TypeUtils.getClassDescriptor(extensionReceiverType) == objCObject - } + val objCObjectRawPtr = packageScope.getContributedFunctions("objcPtr").single() val getObjCReceiverOrSuper = packageScope.getContributedFunctions("getReceiverOrSuper").single()