3

Im trying to convert an exsisting c code to kotlin, with an native library. so far ive successfully got started but struggeling by the pointers that are used to get access to structures or objects. like this in c:

void *ptr;
foo(&ptr); //init is done inside
bar(&ptr); //ptr is reused

but how to keep those pointers in kotlin? attempts like this:

var avar = CPointerVarOf<COpaquePointer>(NativePtr.NULL)
var bvar: CPointerVarOf<CPointer<*>> = null

results in

Native interop types constructors must not be called directly

ive read: kotlin inerop

Any hint is appreciated.

Basur
  • 339
  • 1
  • 14

2 Answers2

4

I've found an working solution. I made an mistake and thought that my pointer allocation is wrong so ive copied out what the ide thought were right. that resulted in an allocation like:

var avar:COpaquePointerVar = alloc()

now Kotlin native allocates all correctly. but the pure allocation rarely solves problem so here is the code:

/* C Code */
void* adapter;
int ret;

ret = gattlib_adapter_open(NULL, &adapter);
if (ret) {
    fprintf(stderr, "ERROR: Failed to open adapter.\n");
    return 1;
}

ret = gattlib_adapter_scan_enable(adapter, ble_discovered_device, 5, NULL /* user_data */);
if (ret) {
    fprintf(stderr, "ERROR: Failed to scan.\n");
}

gattlib_adapter_scan_disable(adapter);

puts("Scan completed");

after i noticed my mistake, i've read all my code again and created an working example in c. I moved the code part by part from c to kotlin native. so the kotlin version has gone through several stages and ended with:

/* Kotlin with native interop */
memScoped {
    var avar: COpaquePointerVar = alloc()
    var ret = gattlib_adapter_open(null, avar.ptr)
    print("Adapter opened\n")
    if (ret > 0) {
        print( "ERROR: Failed to open adapter.\n");
        return
    }

    print("start scan\n")
    gattlib_adapter_scan_enable(avar.value, staticCFunction { a, b, c, d ->
        kotlin.native.initRuntimeIfNeeded()
        print("found dev\n")
    }, 5, NULL /* user_data */);

    gattlib_adapter_scan_disable(avar.value)

    print("Scan completed\n");
}

I,m a student so this might be not best practice, feel free to correct me at any point. I hope that this snippet helps anyone who has just started with kotlin native.

Basur
  • 339
  • 1
  • 14
1

@Basur! One cannot directpy instantiate pointer types. Try to allocate them on the heap, or inside of the memScoped {...} block like this:

val voidy:COpaquePointerVar = nativeHeap.alloc()
fun a(ptr:CPointer<COpaquePointerVar>){
    println(ptr.pointed.value)
    ptr.pointed.value = NULL
}
fun b(ptr:CPointer<COpaquePointerVar>){
    println(ptr.pointed.value)
}
a(voidy.ptr)
b(voidy.ptr)
...
nativeHeap.free(voidy)
Artyom Degtyarev
  • 2,704
  • 8
  • 23
  • yeah, took about 16h to me to realize that and another 3 to find my mistake in code... – Basur Apr 06 '20 at 14:05
  • i wrote an answer while you posted this, feels a bit stupid if i now see and realized where my mistake were, i might build an collection of kotlin native examples for beginners, may i use your code by an link or direct with an reference to your post? – Basur Apr 06 '20 at 14:23
  • Okay, feel free to use it with no mentions at all, your one is even better IMHO. The only thing I would recommend you is to update your answer a bit: there is no need to specify the type explicitly as you did, something like `val avar:COpaquePointerVar = alloc()` should do the trick. – Artyom Degtyarev Apr 06 '20 at 14:56