I am trying to implement kotlin-native dynamic library and use it in c++ code. For example, I have the following code, a function that creates an instance of ResponseImpl and returns interface Response
interface Response
class ResponseImpl(val text: String) : Response
fun getResponse(): Response = ResponseImpl(text = "This is the ResponseImpl instance")
The task ./gradlew :shared:linkReleaseSharedMacosX64 generates for me this lines in header file:
struct {
struct {
struct {
struct {
struct {
libNativeTest_kref_com_test_nativesample_Response (*getResponse)();
struct {
libNativeTest_KType* (*_type)(void);
} Response;
struct {
libNativeTest_KType* (*_type)(void);
libNativeTest_kref_com_test_nativesample_ResponseImpl (*ResponseImpl)(const char* text);
const char* (*get_text)(libNativeTest_kref_com_test_nativesample_ResponseImpl thiz);
} ResponseImpl;
} nativesample;
} test;
} com;
} root;
} kotlin;
} libNativeTest_ExportedSymbols;
In c++ code I call getResponse() function and try to access text property. isInstance is always true but the text property is always null.
#include <iostream>
#include "libNativeTest_api.h"
int main() {
auto lib = libNativeTest_symbols();
auto packet = lib->kotlin.root.com.test.nativesample;
auto response = packet.getResponse();
bool isInstance = lib->IsInstance(response.pinned, packet.ResponseImpl._type());
if (isInstance) {
auto casted_response = (libNativeTest_kref_com_test_nativesample_ResponseImpl *) response.pinned;
auto text = packet.ResponseImpl.get_text(*casted_response);
if (text == nullptr) {
std::cout << "TEXT IS NULL" << std::endl;
} else {
std::cout << text << std::endl;
}
}
return 0;
}
What is the proper way to cast Kotlin interface to its implementation class to access the details?
// Response.kt
// just onto root package
interface Response
class ResponseImpl(val text: String) : Response
fun getResponse(): Response = ResponseImpl(text = "This is the ResponseImpl instance")
No need to use pinned
, where pinned
cannot be cast to (libNativeTest_kref_com_test_nativesample_ResponseImpl *)
// main.c
#include <stdio.h>
#include "libnative_api.h"
int main(int argc, char **argv) {
libnative_ExportedSymbols *symbols = libnative_symbols();
libnative_kref_Response response = symbols->kotlin.root.getResponse();
libnative_kref_ResponseImpl *responseImpl = (libnative_kref_ResponseImpl*)&response;
printf("Response: %s\n", symbols->kotlin.root.ResponseImpl.get_text(*responseImpl));
return 0;
}
//output
Response: This is the ResponseImpl instance