From 6a2812a2d514cecf6d98abc7ae01c6e1e8e2927a Mon Sep 17 00:00:00 2001 From: SvyatoslavScherbina Date: Fri, 18 Oct 2019 18:54:52 +0300 Subject: [PATCH] Initialize ObjCExport during runtime init too (#3471) as it may be required during execution of Kotlin code calling Obj-C. --- backend.native/tests/interop/objc/smoke.kt | 3 ++- runtime/src/main/cpp/ObjCExport.mm | 14 +++++++++++++- runtime/src/main/cpp/ObjCExportInit.h | 15 +++++++++++++++ runtime/src/main/cpp/ObjCExportPrivate.h | 1 - runtime/src/main/cpp/Runtime.cpp | 6 ++++++ runtime/src/objc/cpp/ObjCExportClasses.mm | 1 + 6 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 runtime/src/main/cpp/ObjCExportInit.h diff --git a/backend.native/tests/interop/objc/smoke.kt b/backend.native/tests/interop/objc/smoke.kt index 9c94459475f..aab0cf03676 100644 --- a/backend.native/tests/interop/objc/smoke.kt +++ b/backend.native/tests/interop/objc/smoke.kt @@ -15,8 +15,8 @@ fun main(args: Array) { } fun run() { - testTypeOps() testConversions() + testTypeOps() testWeakRefs() testExceptions() testBlocks() @@ -191,6 +191,7 @@ fun testConversions() { testMethodsOfAny(emptyList(), NSArray()) testMethodsOfAny(listOf(1, "foo"), nsArrayOf(1, "foo")) testMethodsOfAny(42, NSNumber.numberWithInt(42), 17) + testMethodsOfAny(true, NSNumber.numberWithBool(true), false) } fun testMethodsOfAny(kotlinObject: Any, equalNsObject: NSObject, otherObject: Any = Any()) { diff --git a/runtime/src/main/cpp/ObjCExport.mm b/runtime/src/main/cpp/ObjCExport.mm index ee4ea6c9865..55ee2fbf158 100644 --- a/runtime/src/main/cpp/ObjCExport.mm +++ b/runtime/src/main/cpp/ObjCExport.mm @@ -36,6 +36,7 @@ #import #import "ObjCExport.h" +#import "ObjCExportInit.h" #import "ObjCExportPrivate.h" #import "MemoryPrivate.hpp" #import "Runtime.h" @@ -321,7 +322,7 @@ static void initTypeAdapters() { initTypeAdaptersFrom(Kotlin_ObjCExport_sortedProtocolAdapters, Kotlin_ObjCExport_sortedProtocolAdaptersNum); } -extern "C" void Kotlin_ObjCExport_initialize() { +static void Kotlin_ObjCExport_initializeImpl() { initTypeAdapters(); SEL toKotlinSelector = Kotlin_ObjCExport_toKotlinSelector; @@ -363,6 +364,17 @@ extern "C" void Kotlin_ObjCExport_initialize() { } } +// Initializes ObjCExport for current process (if not initialized yet). +// Generally this is equal to some "binary patching" (which is usually done at link time +// but postponed until runtime here due to various reasons): +// adds methods to Objective-C classes, initializes static memory with "constant" values etc. +extern "C" void Kotlin_ObjCExport_initialize() { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Kotlin_ObjCExport_initializeImpl(); + }); +} + static OBJ_GETTER(SwiftObject_toKotlinImp, id self, SEL cmd) { RETURN_RESULT_OF(Kotlin_ObjCExport_convertUnmappedObjCObject, self); } diff --git a/runtime/src/main/cpp/ObjCExportInit.h b/runtime/src/main/cpp/ObjCExportInit.h new file mode 100644 index 00000000000..142f5e104e0 --- /dev/null +++ b/runtime/src/main/cpp/ObjCExportInit.h @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_OBJCEXPORTINIT_H +#define RUNTIME_OBJCEXPORTINIT_H + +#if KONAN_OBJC_INTEROP + +extern "C" void Kotlin_ObjCExport_initialize(void); + +#endif // KONAN_OBJC_INTEROP + +#endif // RUNTIME_OBJCEXPORTINIT_H diff --git a/runtime/src/main/cpp/ObjCExportPrivate.h b/runtime/src/main/cpp/ObjCExportPrivate.h index 57aa89c6521..5628e15ce46 100644 --- a/runtime/src/main/cpp/ObjCExportPrivate.h +++ b/runtime/src/main/cpp/ObjCExportPrivate.h @@ -19,7 +19,6 @@ @end; extern "C" void Kotlin_ObjCExport_initializeClass(Class clazz); -extern "C" void Kotlin_ObjCExport_initialize(void); extern "C" const TypeInfo* Kotlin_ObjCExport_getAssociatedTypeInfo(Class clazz); extern "C" OBJ_GETTER(Kotlin_ObjCExport_convertUnmappedObjCObject, id obj); extern "C" SEL Kotlin_ObjCExport_toKotlinSelector; diff --git a/runtime/src/main/cpp/Runtime.cpp b/runtime/src/main/cpp/Runtime.cpp index 6242d984dd4..ed4cad9f9af 100644 --- a/runtime/src/main/cpp/Runtime.cpp +++ b/runtime/src/main/cpp/Runtime.cpp @@ -19,6 +19,7 @@ #include "Exceptions.h" #include "KAssert.h" #include "Memory.h" +#include "ObjCExportInit.h" #include "Porting.h" #include "Runtime.h" #include "Worker.h" @@ -97,6 +98,11 @@ RuntimeState* initRuntime() { if (firstRuntime) { isMainThread = 1; konan::consoleInit(); + +#if KONAN_OBJC_INTEROP + Kotlin_ObjCExport_initialize(); +#endif + InitOrDeinitGlobalVariables(INIT_GLOBALS); } InitOrDeinitGlobalVariables(INIT_THREAD_LOCAL_GLOBALS); diff --git a/runtime/src/objc/cpp/ObjCExportClasses.mm b/runtime/src/objc/cpp/ObjCExportClasses.mm index b35936c3f48..c366c4668a7 100644 --- a/runtime/src/objc/cpp/ObjCExportClasses.mm +++ b/runtime/src/objc/cpp/ObjCExportClasses.mm @@ -21,6 +21,7 @@ #import #import "ObjCExport.h" +#import "ObjCExportInit.h" #import "ObjCExportPrivate.h" #import "MemoryPrivate.hpp" #import "Runtime.h"