How to map an array of custom objects between kotlin-native and c

Hello,
I use kotlin multiplatform to develop a shared library for android and windows and have a custom data exchange object to interact between the library and the main program.

My kotlin library provides some functions like this:

fun doSomeGreatStuff(input: Array<CustomData>)  : Array<CustomData> {....}

Where CustomData is a data class that contains a bundle of properies.

On the C side, I have a std::list object which contains my CustomData objects. But how can I map this list into the kotlin list and vice versa?

To convert kotlin to c it something like this, I think. But I can’t set the value

 fun List<Media>.toCArray() = memScoped {

          val cArray = allocArray<CPointer<CustomData>>(size)
          forEachIndexed() { index, value ->
                     cArray[index] = value.objcPtr() //doesnt work
                  }
          }

Must I implement CVariable for this?

best greetings and thank you

Hello, @swi! Can you clarify a little bit, are those classes interop’ted from the C side, or you declare them in Kotlin?

Hi @Artyom.Degtyarev. All clases are part of the kotlin code and compiled as a dynamic library.
One of them is a data class.
This library I included in c++ project. In this project I want to create a list of CustomData and Media objects and calling some kotlin functions.
The list of objects is one argument of the kotlin function. The kotlin functions also returns a List of this objects. So, how to map the lists between kotlin and c?

You can either expose Kotlin’s collection as a kref_kotlin_collection or allocate StableRef’s to your objects and use them from the C side. To get more familiar with StableRef, please consider a look through this paragraph.

yeah, I allready exposed the kref_kotlin_collection to c.
But is it possible to create a new kref_kotlin_collection from c and fill it with values?

Yes, that can be done, but probably it will be not so easy. One should wrap all functions, that are going to be called from C, to make them accessible. In your case, I suppose it should be
1)listOf() utilising CArrayPointer; and
2) SomeData initializer, that returns COpaquePointer to it.
Also, I think you would like to upvote this GH issue.

okay, thank you! I will give a try

Hi @Artyom.Degtyarev can you explain how to build a listOf() function? Or is there a minimalistic example how to deal with arrays that contains custom objects? I have no idea beause the CArrayPointer expect a CVariable.

I’ve made a quick example, see below. It is kinda ugly as it iterates over C array, but maybe it can help you for the beginning:
sample.kt

package sample

import kotlinx.cinterop.*

data class SomeData(val contents:String = "SampleText")

fun placeClass(): COpaquePointer {
	val inst = SomeData()
	println("I made another SomeData instance")
	return StableRef.create(inst).asCPointer()
}

fun makeList(ptr: CArrayPointer<COpaquePointerVar>, size:Int): List<SomeData> {
	val intermediate = ArrayList<SomeData>()
	for (index in 0 .. size-1){
		val ref = ptr[index]!!.asStableRef<SomeData>()
		intermediate.add(ref.get())
		ref.dispose()
		println("I disposed another SomeData StableRef and added it's content to List")
	}
	println(intermediate.joinToString())
	return intermediate.toList()
}

use.c

#include "dynamic_api.h"

int main()
{
    dynamic_ExportedSymbols* lib = dynamic_symbols();
    void* array[5];
    for (int i = 0; i < 5; ++i)
    {
        array[i] =lib->kotlin.root.sample.placeClass();
    }
    lib->kotlin.root.sample.makeList(array, 5);
    return 0;
}
1 Like

Ah, thats the key! So, now it works.
You’re right, it is very ugly to iterate over the objects in C. But it is even more annoying that the properties are only accessible via an function call.

Thank you very much!