blob: 964615da7ff975c51cf8c895d5a0c78c2df1baf0 [file]
// TARGET_BACKEND: NATIVE
// MODULE: cinterop
// FILE: cStringOverloads.def
headers = cStringOverloads.h
// FILE: cStringOverloads.h
const char* cstr_identity(const char* s);
int cstr_len(const char* s);
// FILE: cStringOverloads.c
#include <string.h>
#include "cStringOverloads.h"
const char* cstr_identity(const char* s) {
return s;
}
int cstr_len(const char* s) {
return s ? (int)strlen(s) : -1;
}
// MODULE: main(cinterop)
// FILE: main.kt
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import cStringOverloads.*
import kotlinx.cinterop.*
import kotlin.test.*
fun box(): String {
// String overload
assertEquals(5, cstr_len("hello"))
assertEquals(0, cstr_len(""))
// CValuesRef overload
val s = "hello world"
val roundTripped = memScoped {
val inPtr = s.cstr.ptr
val outPtr = cstr_identity(inPtr)!!
outPtr.toKString()
}
assertEquals(s, roundTripped)
assertEquals(s.length, cstr_len(s.cstr))
// `null` matches both overloads. `@LowPriorityInOverloadResolution` on the `CValuesRef`
// variant resolves the ambiguity by choosing the `String?` overload, preserving the
// pre-dual-overload behavior.
assertEquals(-1, cstr_len(null))
// `::cstr_len` must resolve to the `String?` overload to preserve
// the behavior that existed before the dual-overload feature: calling the reference
// with a Kotlin String literal must compile. Requires `@LowPriorityInOverloadResolution`
// on the `CValuesRef` overload, not on the `String?` one.
val ref = ::cstr_len
assertEquals(5, ref("hello"))
val ref2: (CValuesRef<ByteVar>?) -> Int = ::cstr_len
assertEquals(5, ref2("hello".cstr))
return "OK"
}