I trying to discover how to invoke Kotlin code from C in which in Kotlin a function is defined which requires a class type parameter which needs to be implemented in C.
I have a test application that should print a message to stdout using the Kotlin native C interfacing. The code consists of a Kotlin part that is compiled to a native library and C code that is compiled into an executable that uses the Kotlin native library. The implementation makes use of a callback mechanism, at startup the C code creates an instance of the library and calls an initialization function which requires a callback class parameter. Next a Kotlin native library function is called that uses the callback class to print a message to stdout. The final goal is to implement the interface definition of the callback class in C and forward it to the Kotlin native library.
Up till now I was not successful in finding the correct construct to provide the callback object to the native Kotlin library, every attempt results in a SEGFAULT. How do I use the provided structures in the generated header in C to accomplish what I’m trying to do? Or is this construct not supported yet? are there any alternative constructs that I can use? in
Kotlin Code:
hello.kt
package com.hello
class Hello {
private var greeter: Greeter? = null
fun initialize(greeter: Greeter) {
this.greeter = greeter
}
fun sayHello(): String {
return this.greeter?.greet() ?: "Nothing to say..."
}
}
Greeter.kt
package com.hello
interface Greeter {
fun greet(): String
}
Generated header libhello_api.h
#ifndef KONAN_LIBHELLO_H
#define KONAN_LIBHELLO_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
typedef bool libhello_KBoolean;
#else
typedef _Bool libhello_KBoolean;
#endif
typedef unsigned short libhello_KChar;
typedef signed char libhello_KByte;
typedef short libhello_KShort;
typedef int libhello_KInt;
typedef long long libhello_KLong;
typedef unsigned char libhello_KUByte;
typedef unsigned short libhello_KUShort;
typedef unsigned int libhello_KUInt;
typedef unsigned long long libhello_KULong;
typedef float libhello_KFloat;
typedef double libhello_KDouble;
typedef float __attribute__ ((__vector_size__ (16))) libhello_KVector128;
typedef void* libhello_KNativePtr;
struct libhello_KType;
typedef struct libhello_KType libhello_KType;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Byte;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Short;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Int;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Long;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Float;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Double;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Char;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Boolean;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_kotlin_Unit;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_com_hello_Greeter;
typedef struct {
libhello_KNativePtr pinned;
} libhello_kref_com_hello_Hello;
typedef struct {
/* Service functions. */
void (*DisposeStablePointer)(libhello_KNativePtr ptr);
void (*DisposeString)(const char* string);
libhello_KBoolean (*IsInstance)(libhello_KNativePtr ref, const libhello_KType* type);
libhello_kref_kotlin_Byte (*createNullableByte)(libhello_KByte);
libhello_kref_kotlin_Short (*createNullableShort)(libhello_KShort);
libhello_kref_kotlin_Int (*createNullableInt)(libhello_KInt);
libhello_kref_kotlin_Long (*createNullableLong)(libhello_KLong);
libhello_kref_kotlin_Float (*createNullableFloat)(libhello_KFloat);
libhello_kref_kotlin_Double (*createNullableDouble)(libhello_KDouble);
libhello_kref_kotlin_Char (*createNullableChar)(libhello_KChar);
libhello_kref_kotlin_Boolean (*createNullableBoolean)(libhello_KBoolean);
libhello_kref_kotlin_Unit (*createNullableUnit)(void);
/* User functions. */
struct {
struct {
struct {
struct {
struct {
libhello_KType* (*_type)(void);
const char* (*greet)(libhello_kref_com_hello_Greeter thiz);
} Greeter;
struct {
libhello_KType* (*_type)(void);
libhello_kref_com_hello_Hello (*Hello)();
void (*initialize)(libhello_kref_com_hello_Hello thiz, libhello_kref_com_hello_Greeter greeter);
void (*sayHello)(libhello_kref_com_hello_Hello thiz);
} Hello;
} hello;
} com;
} root;
} kotlin;
} libhello_ExportedSymbols;
extern libhello_ExportedSymbols* libhello_symbols(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* KONAN_LIBHELLO_
‘C’ Code:
#include "libhello_api.h"
const char* greet(libhello_kref_com_hello_Greeter g) {
return "Hello from Greeter";
}
int main() {
// Get pointer to library root object
libhello_ExportedSymbols* lib = libhello_symbols();
// Get the hello object (thizz)
libhello_kref_com_hello_Hello thizz = lib->kotlin.root.com.hello.Hello.Hello();
libhello_kref_com_hello_Greeter greeterPtr;
// set the greet function inside the Greeter object
lib->kotlin.root.com.hello.Greeter.greet = greet;
// set the pointer to the Greeter object
greeterPtr.pinned = &lib->kotlin.root.com.hello.Greeter;
// call the initialize function with the pointer to Greeter
lib->kotlin.root.com.hello.Hello.initialize(thizz, greeterPtr);
// call the sayHello function which should point to the greet() function declared above
lib->kotlin.root.com.hello.Hello.sayHello(thizz);
return 0;
}