Closed ArthurBrum closed 4 years ago
Just in case, the code I'm trying to run is:
package com.fidential.project
import com.github.florent37.log.Logger
import platform.darwin.NSObject
fun makeBTest() = BTest()
actual class BTest {
val TAG = "BTest"
private val delegate = object : NSObject(), LibDeviceSearchListenerProtocol {
override fun discoveredDevice(reader: LibDevice?) {
Logger.d(TAG, reader?.name ?: "None found")
}
override fun discoveryComplete() {
Logger.d(TAG, "discoveryComplete.")
}
}
var deviceManager: LibDeviceManagerProtocol? = null
actual fun startSearch() {
this.deviceManager = Lib.getDeviceManager(LibDeviceTypeEnum.LibDeviceTypeValue01)
this.deviceManager?.searchDevicesWithLowRSSI(-124, 100, this.delegate)
Logger.d(TAG, "Got here!! \n")
}
}
And I'm calling
let a = BTestKt.makeBTest()
a.startSearch()
in my iOS app. And about isReachOS
, its not in my code neither in the headers that I have access of this Lib
Well, I'm not experienced at using lldb, but how could I add breakpoints to my app files? I dont know the name of files generated. I tried:
objc[359]: Class _NSZombie_OS_dispatch_data is implemented in both ?? (0x281b2ea60) and ?? (0x281b52bb0). One of the two will be used. Which one is undefined.
objc[359]: Class _NSZombie_OS_xpc_data is implemented in both ?? (0x281b52d90) and ?? (0x281b2ee50). One of the two will be used. Which one is undefined.
BTest : Got here!!
2020-02-11 08:38:12.755820-0300 iosApp[359:50145] +[BLEDeviceInfo isReachOS:]: unrecognized selector sent to class 0x100d19818
2020-02-11 08:38:12.763249-0300 iosApp[359:50145] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[BLEDeviceInfo isReachOS:]: unrecognized selector sent to class 0x100d19818'
*** First throw call stack:
(0x1fb43b180 0x1fa6139f8 0x1fb35ca08 0x1fb4409c8 0x1fb44265c 0x100c1b4cc 0x200f55114 0x200f561f0 0x200f64438 0x10097b6f4 0x10097cc78 0x100984bf4 0x1009858ec 0x100984a4c 0x1009858b4 0x10098f77c 0x1fb05a114 0x1fb05ccd4)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) b -a 0x100d19818
Breakpoint 1: where = BC_lib`BLEDeviceInfo, address = 0x0000000100d19818
(lldb) b -a 0x281b2ea60
Breakpoint 2: address = 0x0000000281b2ea60
(lldb) b -a 0x281b52bb0
Breakpoint 3: address = 0x0000000281b52bb0
(lldb) b -a 0x1fb43b180
Breakpoint 4: where = CoreFoundation`__exceptionPreprocess + 228, address = 0x00000001fb43b180
(lldb) b -a 0x1fa6139f8
Breakpoint 5: where = libobjc.A.dylib`objc_exception_throw + 56, address = 0x00000001fa6139f8
(lldb) b -a 0x1fb35ca08
Breakpoint 6: where = CoreFoundation`+[NSOrderedSet orderedSetWithSet:], address = 0x00000001fb35ca08
(lldb) b -a 0x1fb44265c
Breakpoint 7: where = CoreFoundation`_CF_forwarding_prep_0 + 92, address = 0x00000001fb44265c
(lldb) b -a 0x1fb4409c8 0x100c1b4cc 0x200f55114
Breakpoint 8: where = CoreFoundation`___forwarding___ + 1408, address = 0x00000001fb4409c8
(lldb) b -a 0x100c1b4cc
Breakpoint 9: where = BC_lib`-[BLEClientDriver centralManager:didDiscoverPeripheral:advertisementData:RSSI:] + 376, address = 0x0000000100c1b4cc
(lldb) b -a 0x200f55114
Breakpoint 10: where = CoreBluetooth`-[CBCentralManager handlePeripheralDiscovered:] + 1060, address = 0x0000000200f55114
(lldb) b -a 0x200f561f0
Breakpoint 11: where = CoreBluetooth`-[CBCentralManager handleMsg:args:] + 620, address = 0x0000000200f561f0
(lldb) b -a 0x200f64438
Breakpoint 12: where = CoreBluetooth`__30-[CBXpcConnection _handleMsg:]_block_invoke + 60, address = 0x0000000200f64438
(lldb) b -a 0x10097b6f4
Breakpoint 13: where = libdispatch.dylib`_dispatch_call_block_and_release + 24, address = 0x000000010097b6f4
(lldb) b -a 0x10097cc78
Breakpoint 14: where = libdispatch.dylib`_dispatch_client_callout + 16, address = 0x000000010097cc78
(lldb) b -a 0x100984bf4
Breakpoint 15: where = libdispatch.dylib`_dispatch_lane_serial_drain + 712, address = 0x0000000100984bf4
(lldb) b -a 0x1009858ec
Breakpoint 16: where = libdispatch.dylib`_dispatch_lane_invoke + 512, address = 0x00000001009858ec
(lldb) b -a 0x100984a4c
Breakpoint 17: where = libdispatch.dylib`_dispatch_lane_serial_drain + 288, address = 0x0000000100984a4c
(lldb) b -a 0x1009858b4
Breakpoint 18: where = libdispatch.dylib`_dispatch_lane_invoke + 456, address = 0x00000001009858b4
(lldb) b -a 0x10098f77c
Breakpoint 19: where = libdispatch.dylib`_dispatch_workloop_worker_thread + 1148, address = 0x000000010098f77c
(lldb) b -a 0x1fb05a114
Breakpoint 20: where = libsystem_pthread.dylib`_pthread_wqthread + 304, address = 0x00000001fb05a114
(lldb) b -a 0x1fb05ccd4
Breakpoint 21: where = libsystem_pthread.dylib`start_wqthread + 4, address = 0x00000001fb05ccd4
Hi! Have you tried this approach?
Hi! Could you give me instructions on how to compile my framework with debug flags? I'm running into this same issue in several parts of my code now and I really need to fix this :(
As I was searching this symbol "isReachOS" inside the other files, I found it inside the binaries of another framework that I thought was being correctly compiled and linked through cinterop... but it actually wasnt. It was generating just an empty kotlin file inside myProject/build/classes/.../myProject-cinterop-libName.klib-build
And the worst part is that this second framework is partly written in C++, so even if when I fixed the cinterop .def files, it could not add it in my kotlin multiplatform project... It kept giving me
> Task :BcLib:cinteropLibNameIos FAILED
Exception in thread "main" java.lang.Error:
src/nativeInterop/frameworks/LibName.framework/Headers/LDInfoParser.h:190:1: error: unknown type name 'class'
at org.jetbrains.kotlin.native.interop.indexer.UtilsKt.ensureNoCompileErrors(Utils.kt:146)
at org.jetbrains.kotlin.native.interop.indexer.IndexerKt.indexDeclarations(Indexer.kt:966)
at org.jetbrains.kotlin.native.interop.indexer.IndexerKt.buildNativeIndexImpl(Indexer.kt:955)
at org.jetbrains.kotlin.native.interop.indexer.NativeIndexKt.buildNativeIndex(NativeIndex.kt:91)
at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.processCLib(main.kt:221)
at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.interop(main.kt:39)
at org.jetbrains.kotlin.cli.utilities.InteropCompilerKt.invokeInterop(InteropCompiler.kt:71)
at org.jetbrains.kotlin.cli.utilities.MainKt.main(main.kt:18)
Is it possible to solve this by importing one framework in my kotlin multiplatform project and this second one in xcode? I tried removing the second one from the gradle and it started asking for some symbols (that are from the removed framework). I tried some other ways, got to successful compilation, but crashed in runtime when launching from xcode). I don't need to call any function from this second lib, it just have to be there because this first ObjC framework is calling it under the hoods, so its probably just about linking it correctly... Does anyone has any idea? or just opinions if this could ever work??
Thanks in advance!
Hello again, @ArthurBrum. Can you clarify a little, what is the current status of your problem? It seems like you found the root cause successfully, but cannot separate framework to be interop'ted from one that has to be attached to the Xcode project, am I right? If this is correct, then you're probably doing everything fine. The crash you experience now, is it the same as one from the topic start? What are those "other ways" you mention?
Hello again, @ArthurBrum. Can you clarify a little, what is the current status of your problem? It seems like you found the root cause successfully, but cannot separate framework to be interop'ted from one that has to be attached to the Xcode project, am I right? If this is correct, then you're probably doing everything fine. The crash you experience now, is it the same as one from the topic start?
Yes, you understood it correctly. The issue is still the same. I still can not make my lib use the function 'isReachOS' successfully.
(To be clear: this function, I don't need to call it directly, it's just being called under the hood... That is, I only call Lib_One directly in my project. Lib_One calls Lib_Two and Lib_Two has this isReachOS somewhere in its binaries, but not in its headers.)
What are those "other ways" you mention?
So, to explain my attempts better, I'll clarify the files I had for each situation:
In here, I thought I was using the 2 frameworks correctly, but just Lib_One was generating a useful
kotlin file from the cinterop'ing process. Lib_Two was generating an empty kotlin file inside
myProject/build/classes/.../myProject-cinterop-libName.klib-build
(...)
fromPreset(iosTarget, 'ios') {
binaries {
framework('BC_lib'){
linkerOpts "-Fsrc/nativeInterop/frameworks"
}
}
compilations.main {
cinterops {
Lib_One {
packageName 'com.fidential.bclib'
compilerOpts '-Isrc/nativeInterop/frameworks/Lib_One.framework/Headers'
}
Lib_Two {
packageName 'com.fidential.bclib'
compilerOpts '-Isrc/nativeInterop/frameworks/Lib_Two.framework/Headers'
}
}
}
}
(...)
language = Objective-C
package = com.fidential.bclib
headers = Lib_One.h
linkerOpts = -framework Lib_One -framework UIKit -framework CoreBluetooth
language = Objective-C
package = com.fidential.bclib
headerFilter = *.h
linkerOpts = -framework Lib_Two
Just including my BC_lib.framework (that is always generated by my kmp project)
As result of this first trial, I ran into the errors of my last comment
error: unknown type name 'class'
I think it happened because cinterop currently doesnt support C++ headers
language = Objective-C
package = com.fidential.bclib
headers = several.h \
other.h \
header.h \
files.h
linkerOpts = -framework Lib_Two
(...)
fromPreset(iosTarget, 'ios') {
binaries {
framework('BC_lib'){
linkerOpts "-Fsrc/nativeInterop/frameworks"
}
}
compilations.main {
cinterops {
Lib_One {
packageName 'com.fidential.bclib'
compilerOpts '-Isrc/nativeInterop/frameworks/Lib_One.framework/Headers'
}
}
}
}
(...)
As result, I got gradle compiling errors like:
> Task :BcLib:linkBC_libDebugFrameworkIos
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_LDBluetoothManager", referenced from:
objc-class-ref in Lib_One(DeviceCode-DeviceManager.o)
"_OBJC_CLASS_$_RDeviceInfo", referenced from:
objc-class-ref in LibOne(NameReader.o)
(...)
Which I know are symbols that exist in Lib_Two headers
(Just added -framework Lib_Two
at the end of linkerOpts of Lib_One.def)
language = Objective-C
package = com.fidential.bclib
headers = Lib_One.h
linkerOpts = -framework Lib_One -framework UIKit -framework CoreBluetooth -framework Lib_Two
Here I got the same error saying isReachOS
couldnt be found.
No success, same error as Attempt 3
Also, from the provider of the frameworks, I have some sample projects that includes both Lib_One and Lib_Two and another lib called libc++.tdb
I dont know if it makes any difference, but I think I should mention it
I suppose that libc++
should not affect your case. In the Xcode, are you adding this Lib_Two.framework to the result app target or the kotlin-produced framework? I think it should be in the framework build phases, like in this manual.
Are you registered in the kotlinlang Slack? The community there is much more responsive, as we use GH mostly for reporting bugs.
Hey @artdfel! Thanks for helping me out!
I finally managed to fix it.
I just added some flags to my Lib_One.def like:
linkerOpts = -all_load -ObjC -lc++ -framework Lib_One -framework Lib_Two
And it works!!!
I wonder why it was needed, but found it with the help of a friend at work, he logged the ld
command called by xcode in the sample projects and figure it out!
And also thanks for the advice, I'll try talking to the community through the kotlinlang slack then!!
In my project, I'm using an Objective-C library through cinterop. The external libs are used to connect with bluetooth devices and has dependencies with CoreBluetooth, ExternalAccessory and other Apple frameworks. I'm not totally sure if I have all my targets and sources settings correctly, but you can check details about my build.gradle files here https://github.com/JetBrains/kotlin-native/issues/3827#issue-560593909 if someone think it could help...
But when I try to run a simple scan for devices, I get these errors on the logs from xcode:
Maybe I have a smaller problem here with duplicated linked libraries, but I think the bigger one is that I cannot know which are the classes referenced by these errors. Is there a better way to debug this instead of using lldb? Can I export the references for the classes somehow?