Jeff Lockhart
07/06/2022, 12:56 AMexternal expect fun
definitions to a pre-defined ObjC interop? I'm using an ObjC cocoapods library and need to call a function that's not part of its public API for testing. I know the function signature from its source code. Basically, I just need a way to ObjC "message" the function in Kotlin. Or something akin to Java reflection to access it.Rick Clephas
07/07/2022, 6:40 AM.def
file you could add custom declarations:
https://kotlinlang.org/docs/native-c-interop.html#add-custom-declarationsJeff Lockhart
07/07/2022, 7:12 AM.def
file in the project is build/cocoapods/defs/LibName.def. And the contents is:
language = Objective-C
modules = LibName
I'm not aware of a way to modify this, since the cocoapods plugin handles generating the interop. Is it possible to define another .def
file for the same library?Rick Clephas
07/07/2022, 7:24 AM.def
file and/or use a custom .def
file.
The cinterops can be created/accessed in the build.gradle.kts
file: https://github.com/rickclephas/NSErrorKt/blob/17f92767016c9401cff6f3fc371c627cc41e693b/nserror-kt/build.gradle.kts#L44
Haven’t looked at the source of the cocoapods plugin, but I assume they are using the same feature. In that case your cocoapods library should have a cinterop “task”.Jeff Lockhart
07/07/2022, 7:25 AM@ObjCMethod
annotation:
@ObjCMethod(selector = "methodName", encoding = "@16@0:8")
private external fun ObjCClass.methodName(): Boolean
I mostly stumbled upon this solution with trial and error. I can't find its usage documented anywhere. The encoding
parameter is the hard part. I'm assuming I can find this somewhere from the ObjC compiler output. But @16@0:8
seems to be valid for methods that have no parameters and works at least for the Boolean
return type of the method I needed. I based this off this code snippet and it just happened to work when I tried in my own code.
I'll have to look more into how best to get an ObjC method's encoding.Rick Clephas
07/07/2022, 10:44 AM.def
file:
tasks.named<org.jetbrains.kotlin.gradle.tasks.DefFileTask>("generateDef${pod.moduleName}") {
doLast {
outputFile.appendText("""
---
static inline int getErrno() {
return errno;
}
""".trimIndent())
}
}
Jeff Lockhart
07/08/2022, 4:43 AMRick Clephas
07/08/2022, 5:19 AMJeff Lockhart
07/08/2022, 8:47 PMRick Clephas
07/08/2022, 9:01 PMJeff Lockhart
07/08/2022, 9:20 PMstatic inline int doesThisWork() {
return 1;
}
I can't find a reference to the function in Kotlin.Rick Clephas
07/09/2022, 9:15 PMfirebaseUserAgent
property from FIRApp
.
With the following .def
file:
language = Objective-C
headers = FirebaseCore/FIRApp.h
headerFilter = FirebaseCore/**
---
@interface FIRApp ()
@property(class, readonly, nullable) NSString *firebaseUserAgent;
@end
I can print the user agent in Kotlin:
import cocoapods.FirebaseCore.FIRApp
import cocoapods.FirebaseCore.firebaseUserAgent
println(FIRApp.firebaseUserAgent)
However the CocoaPods plugin generates the following .def
file:
language = Objective-C
modules = FirebaseCore
When modules
is specified instead of headers
and headerFilter
the interop logic doesn’t include the mainFile
that contains our custom declarations.
@svyatoslav.scherbina any specific reason why the custom declarations aren’t included when modules
is used?svyatoslav.scherbina
07/11/2022, 9:26 AMI did discover a way to define the most important method I need to access, using thePlease note that this annotation is not intended to be used manually, and provides no compatibility guarantees. Also, the encoding is platform-specific.annotation:@ObjCMethod
@svyatoslav.scherbina any specific reason why the custom declarations aren’t included whenLikely a bug. As a workaround, one can patch the generatedis used?modules
.def
file to use headers =
and headerFilter =
instead of modules =
.Jeff Lockhart
07/12/2022, 7:22 AMsvyatoslav.scherbina
07/12/2022, 12:44 PMJeff Lockhart
07/12/2022, 3:00 PMRick Clephas
07/12/2022, 3:56 PMmainFile
to the list of headers), but I am not sure how to cover that with tests 🙂svyatoslav.scherbina
07/12/2022, 5:09 PMcreateInterop
, an include path should be specified).Rick Clephas
07/12/2022, 8:18 PM