Make linkage issues more understandable in Objective-C interop
This commit is contained in:
committed by
SvyatoslavScherbina
parent
a0dc2ecef2
commit
caf6719fc4
@@ -124,6 +124,19 @@ annotation class InteropStubs()
|
|||||||
@Retention(AnnotationRetention.SOURCE)
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
private annotation class ObjCMethodImp(val selector: String, val encoding: String)
|
private annotation class ObjCMethodImp(val selector: String, val encoding: String)
|
||||||
|
|
||||||
|
@konan.internal.ExportForCppRuntime("Kotlin_Interop_getObjCClass")
|
||||||
|
private fun getObjCClassByName(name: NativePtr): NativePtr {
|
||||||
|
val result = objc_lookUpClass(name)
|
||||||
|
if (result == nativeNullPtr) {
|
||||||
|
val className = interpretCPointer<ByteVar>(name)!!.toKString()
|
||||||
|
val message = """Objective-C class '$className' not found.
|
||||||
|
|Ensure that the containing framework or library was linked.""".trimMargin()
|
||||||
|
|
||||||
|
throw RuntimeException(message)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
@konan.internal.ExportForCompiler
|
@konan.internal.ExportForCompiler
|
||||||
private fun <T : ObjCObject> allocObjCObject(clazz: NativePtr): T {
|
private fun <T : ObjCObject> allocObjCObject(clazz: NativePtr): T {
|
||||||
val rawResult = objc_allocWithZone(clazz)
|
val rawResult = objc_allocWithZone(clazz)
|
||||||
@@ -183,3 +196,6 @@ external fun objc_retain(ptr: NativePtr): NativePtr
|
|||||||
|
|
||||||
@SymbolName("Kotlin_objc_release")
|
@SymbolName("Kotlin_objc_release")
|
||||||
external fun objc_release(ptr: NativePtr)
|
external fun objc_release(ptr: NativePtr)
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_objc_lookUpClass")
|
||||||
|
external fun objc_lookUpClass(name: NativePtr): NativePtr
|
||||||
|
|||||||
+1
-1
@@ -2081,7 +2081,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
assert(!classDescriptor.isInterface)
|
assert(!classDescriptor.isInterface)
|
||||||
|
|
||||||
return if (classDescriptor.isExternalObjCClass()) {
|
return if (classDescriptor.isExternalObjCClass()) {
|
||||||
val lookUpFunction = context.llvm.externalFunction("objc_lookUpClass",
|
val lookUpFunction = context.llvm.externalFunction("Kotlin_Interop_getObjCClass",
|
||||||
functionType(int8TypePtr, false, int8TypePtr))
|
functionType(int8TypePtr, false, int8TypePtr))
|
||||||
|
|
||||||
call(lookUpFunction,
|
call(lookUpFunction,
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
Class Kotlin_Interop_getObjCClass(const char* name);
|
||||||
|
|
||||||
struct KotlinClassData {
|
struct KotlinClassData {
|
||||||
const TypeInfo* typeInfo;
|
const TypeInfo* typeInfo;
|
||||||
int32_t bodyOffset;
|
int32_t bodyOffset;
|
||||||
@@ -67,8 +69,7 @@ static void DeallocImp(id self, SEL _cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void AddDeallocMethod(Class clazz) {
|
static void AddDeallocMethod(Class clazz) {
|
||||||
Class nsObjectClass = objc_getClass("NSObject");
|
Class nsObjectClass = Kotlin_Interop_getObjCClass("NSObject");
|
||||||
RuntimeAssert(nsObjectClass != nullptr, "NSObject class not found");
|
|
||||||
|
|
||||||
SEL deallocSelector = sel_registerName("dealloc");
|
SEL deallocSelector = sel_registerName("dealloc");
|
||||||
Method nsObjectDeallocMethod = class_getInstanceMethod(nsObjectClass, deallocSelector);
|
Method nsObjectDeallocMethod = class_getInstanceMethod(nsObjectClass, deallocSelector);
|
||||||
@@ -136,7 +137,7 @@ void* CreateKotlinObjCClass(const KotlinObjCClassInfo* info) {
|
|||||||
className = classNameBuffer;
|
className = classNameBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class superclass = objc_getClass(info->superclassName);
|
Class superclass = Kotlin_Interop_getObjCClass(info->superclassName);
|
||||||
Class newClass = objc_allocateClassPair(superclass, className, sizeof(struct KotlinClassData));
|
Class newClass = objc_allocateClassPair(superclass, className, sizeof(struct KotlinClassData));
|
||||||
RuntimeAssert(newClass != nullptr, "Failed to allocate Objective-C class");
|
RuntimeAssert(newClass != nullptr, "Failed to allocate Objective-C class");
|
||||||
|
|
||||||
@@ -205,6 +206,10 @@ void Kotlin_objc_release(id ptr) {
|
|||||||
objc_release(ptr);
|
objc_release(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Class Kotlin_objc_lookUpClass(const char* name) {
|
||||||
|
return objc_lookUpClass(name);
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
#else // KONAN_OBJC_INTEROP
|
#else // KONAN_OBJC_INTEROP
|
||||||
@@ -236,6 +241,10 @@ void Kotlin_objc_release(void* ptr) {
|
|||||||
RuntimeAssert(false, "Objective-C interop is disabled");
|
RuntimeAssert(false, "Objective-C interop is disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* Kotlin_objc_lookUpClass(const char* name) {
|
||||||
|
RuntimeAssert(false, "Objective-C interop is disabled");
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
#endif // KONAN_OBJC_INTEROP
|
#endif // KONAN_OBJC_INTEROP
|
||||||
|
|||||||
Reference in New Issue
Block a user