Implement equals, hashCode and toString for Objective-C objects
This commit is contained in:
committed by
SvyatoslavScherbina
parent
6b042a5510
commit
4e285a5ef4
@@ -23,9 +23,9 @@ interface ObjCClass : ObjCObject
|
|||||||
typealias ObjCObjectMeta = ObjCClass
|
typealias ObjCObjectMeta = ObjCClass
|
||||||
|
|
||||||
abstract class ObjCObjectBase protected constructor() : ObjCObject {
|
abstract class ObjCObjectBase protected constructor() : ObjCObject {
|
||||||
final override fun equals(other: Any?): Boolean = TODO()
|
final override fun equals(other: Any?): Boolean = this.uncheckedCast<ObjCPointerHolder>().equals(other)
|
||||||
final override fun hashCode(): Int = TODO()
|
final override fun hashCode(): Int = ObjCHashCode(this.rawPtr)
|
||||||
final override fun toString(): String = TODO()
|
final override fun toString(): String = ObjCToString(this.rawPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ObjCObjectBaseMeta protected constructor() : ObjCObjectBase(), ObjCObjectMeta {}
|
abstract class ObjCObjectBaseMeta protected constructor() : ObjCObjectBase(), ObjCObjectMeta {}
|
||||||
@@ -42,9 +42,11 @@ class ObjCPointerHolder(inline val rawPtr: NativePtr) {
|
|||||||
objc_retain(rawPtr)
|
objc_retain(rawPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun equals(other: Any?): Boolean = TODO()
|
final override fun equals(other: Any?): Boolean =
|
||||||
final override fun hashCode(): Int = TODO()
|
(other is ObjCPointerHolder) && ObjCEquals(this.rawPtr, other.rawPtr)
|
||||||
final override fun toString(): String = TODO()
|
|
||||||
|
final override fun hashCode(): Int = ObjCHashCode(this.rawPtr)
|
||||||
|
final override fun toString(): String = ObjCToString(this.rawPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@konan.internal.Intrinsic
|
@konan.internal.Intrinsic
|
||||||
@@ -146,12 +148,22 @@ private external fun <T : ObjCObject> getObjCClass(): NativePtr
|
|||||||
|
|
||||||
// Konan runtme:
|
// Konan runtme:
|
||||||
|
|
||||||
@SymbolName("CreateNSStringFromKString")
|
@SymbolName("Kotlin_Interop_CreateNSStringFromKString")
|
||||||
external fun CreateNSStringFromKString(str: String?): NativePtr
|
external fun CreateNSStringFromKString(str: String?): NativePtr
|
||||||
|
|
||||||
@SymbolName("CreateKStringFromNSString")
|
@SymbolName("Kotlin_Interop_CreateKStringFromNSString")
|
||||||
external fun CreateKStringFromNSString(ptr: NativePtr): String?
|
external fun CreateKStringFromNSString(ptr: NativePtr): String?
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_Interop_ObjCToString")
|
||||||
|
private external fun ObjCToString(ptr: NativePtr): String
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_Interop_ObjCHashCode")
|
||||||
|
private external fun ObjCHashCode(ptr: NativePtr): Int
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_Interop_ObjCEquals")
|
||||||
|
private external fun ObjCEquals(ptr: NativePtr, otherPtr: NativePtr): Boolean
|
||||||
|
|
||||||
|
|
||||||
// Objective-C runtime:
|
// Objective-C runtime:
|
||||||
|
|
||||||
@SymbolName("objc_retainAutoreleaseReturnValue")
|
@SymbolName("objc_retainAutoreleaseReturnValue")
|
||||||
|
|||||||
@@ -2101,7 +2101,8 @@ if (isMac()) {
|
|||||||
|
|
||||||
task interop_objc_smoke(type: RunInteropKonanTest) {
|
task interop_objc_smoke(type: RunInteropKonanTest) {
|
||||||
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
|
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
|
||||||
goldValue = "Hello, World!\nKotlin says: Hello, everybody!\nHello from Kotlin\n2, 1\nDeallocated\nDeallocated\n"
|
goldValue = "Hello, World!\nKotlin says: Hello, everybody!\nHello from Kotlin\n2, 1\n" +
|
||||||
|
"true\ntrue\nDeallocated\nDeallocated\n"
|
||||||
|
|
||||||
source = "interop/objc/smoke.kt"
|
source = "interop/objc/smoke.kt"
|
||||||
interop = 'objcSmoke'
|
interop = 'objcSmoke'
|
||||||
|
|||||||
@@ -23,6 +23,21 @@ fun run() {
|
|||||||
replacePairElements(pair, 1, 2)
|
replacePairElements(pair, 1, 2)
|
||||||
pair.swap()
|
pair.swap()
|
||||||
println("${pair.first}, ${pair.second}")
|
println("${pair.first}, ${pair.second}")
|
||||||
|
|
||||||
|
// equals and hashCode (virtually):
|
||||||
|
val map = mapOf(foo to pair, pair to foo)
|
||||||
|
|
||||||
|
// equals (directly):
|
||||||
|
if (!foo.equals(pair)) {
|
||||||
|
// toString (directly):
|
||||||
|
println(map[pair].toString() + map[foo].toString() == foo.description() + pair.description())
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashCode (directly):
|
||||||
|
if (foo.hashCode() == foo.hash().toInt()) {
|
||||||
|
// toString (virtually):
|
||||||
|
println(map.keys.map { it.toString() }.min() == foo.description())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MutablePairProtocol.swap() {
|
fun MutablePairProtocol.swap() {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
NSString* CreateNSStringFromKString(const ArrayHeader* str) {
|
NSString* Kotlin_Interop_CreateNSStringFromKString(const ArrayHeader* str) {
|
||||||
if (str == nullptr) {
|
if (str == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ NSString* CreateNSStringFromKString(const ArrayHeader* str) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ_GETTER(CreateKStringFromNSString, NSString* str) {
|
OBJ_GETTER(Kotlin_Interop_CreateKStringFromNSString, NSString* str) {
|
||||||
if (str == nullptr) {
|
if (str == nullptr) {
|
||||||
RETURN_OBJ(nullptr);
|
RETURN_OBJ(nullptr);
|
||||||
}
|
}
|
||||||
@@ -73,6 +73,18 @@ OBJ_GETTER(CreateKStringFromNSString, NSString* str) {
|
|||||||
RETURN_OBJ(result->obj());
|
RETURN_OBJ(result->obj());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OBJ_GETTER(Kotlin_Interop_ObjCToString, id <NSObject> ptr) {
|
||||||
|
RETURN_RESULT_OF(Kotlin_Interop_CreateKStringFromNSString, ptr.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
KInt Kotlin_Interop_ObjCHashCode(id <NSObject> ptr) {
|
||||||
|
return (KInt) ptr.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
KBoolean Kotlin_Interop_ObjCEquals(id <NSObject> ptr, id otherPtr) {
|
||||||
|
return [ptr isEqual:otherPtr];
|
||||||
|
}
|
||||||
|
|
||||||
// Note: this body is used for init methods with signatures differing from this;
|
// Note: this body is used for init methods with signatures differing from this;
|
||||||
// it is correct on arm64 and x86_64, because the body uses only the first two arguments which are fixed,
|
// it is correct on arm64 and x86_64, because the body uses only the first two arguments which are fixed,
|
||||||
// and returns pointers.
|
// and returns pointers.
|
||||||
@@ -97,16 +109,31 @@ id MissingInitImp(id self, SEL _cmd) {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void* CreateNSStringFromKString(const ArrayHeader* str) {
|
void* Kotlin_Interop_CreateNSStringFromKString(const ArrayHeader* str) {
|
||||||
RuntimeAssert(false, "Objective-C interop is disabled");
|
RuntimeAssert(false, "Objective-C interop is disabled");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ_GETTER(CreateKStringFromNSString, void* str) {
|
OBJ_GETTER(Kotlin_Interop_CreateKStringFromNSString, void* str) {
|
||||||
RuntimeAssert(false, "Objective-C interop is disabled");
|
RuntimeAssert(false, "Objective-C interop is disabled");
|
||||||
RETURN_OBJ(nullptr);
|
RETURN_OBJ(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OBJ_GETTER(Kotlin_Interop_ObjCToString, KNativePtr ptr) {
|
||||||
|
RuntimeAssert(false, "Objective-C interop is disabled");
|
||||||
|
RETURN_OBJ(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
KInt Kotlin_Interop_ObjCHashCode(KNativePtr ptr) {
|
||||||
|
RuntimeAssert(false, "Objective-C interop is disabled");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
KBoolean Kotlin_Interop_ObjCEquals(KNativePtr ptr, KNativePtr otherPtr) {
|
||||||
|
RuntimeAssert(false, "Objective-C interop is disabled");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
#endif // KONAN_OBJC_INTEROP
|
#endif // KONAN_OBJC_INTEROP
|
||||||
Reference in New Issue
Block a user