| // 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" |
| } |