| /* | |
| * Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license | |
| * that can be found in the LICENSE file. | |
| */ | |
| // KT-86026 TODO: Rework testdata to move functions/globals definitions from .def/.h into separate source files | |
| // TARGET_BACKEND: NATIVE | |
| // WITH_PLATFORM_LIBS | |
| // MODULE: cinterop | |
| // FILE: ccallbacksAndVarargs.def | |
| --- | |
| #include <stdarg.h> | |
| struct S { | |
| int x; | |
| }; | |
| static int getX(struct S (*callback)(void)) { | |
| return callback().x; | |
| } | |
| static void applyCallback(struct S s, void (*callback)(struct S)) { | |
| callback(s); | |
| } | |
| static struct S makeS(int x, ...) { | |
| return (struct S){ x }; | |
| } | |
| enum E { | |
| ZERO, ONE, TWO | |
| }; | |
| static enum E makeE(int ordinal, ...) { | |
| return ordinal; | |
| } | |
| struct Args { | |
| char a1; | |
| char a2; | |
| short a3; | |
| int a4; | |
| long long a5; | |
| float a6; | |
| double a7; | |
| void* a8; | |
| unsigned char a9; | |
| unsigned short a10; | |
| unsigned int a11; | |
| unsigned long long a12; | |
| enum E a13; | |
| struct S a14; | |
| void* a15; | |
| }; | |
| static struct Args getVarargs(int ignore, ...) { | |
| va_list args; | |
| va_start(args, ignore); | |
| struct Args result = { | |
| va_arg(args, char), | |
| va_arg(args, char), | |
| va_arg(args, short), | |
| va_arg(args, int), | |
| va_arg(args, long long), | |
| va_arg(args, double), | |
| va_arg(args, double), | |
| va_arg(args, void*), | |
| va_arg(args, unsigned char), | |
| va_arg(args, unsigned short), | |
| va_arg(args, unsigned int), | |
| va_arg(args, unsigned long long), | |
| va_arg(args, enum E), | |
| va_arg(args, struct S), | |
| va_arg(args, void*) | |
| }; | |
| va_end(args); | |
| return result; | |
| } | |
| static int sum(int first, int second) { | |
| return first + second; | |
| } | |
| // MODULE: main(cinterop) | |
| // FILE: main.kt | |
| @file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class) | |
| import kotlin.test.* | |
| import kotlinx.cinterop.* | |
| import ccallbacksAndVarargs.* | |
| fun box(): String { | |
| testStructCallbacks() | |
| testVarargs() | |
| testCallableReferences() | |
| return "OK" | |
| } | |
| fun testStructCallbacks() { | |
| assertEquals(42, getX(staticCFunction { -> cValue<S> { x = 42 } })) | |
| applyCallback(cValue { x = 17 }, staticCFunction { it: CValue<S> -> | |
| assertEquals(17, it.useContents { x }) | |
| it.useContents { | |
| val xRef = ::x | |
| assertEquals(17, xRef.get()) | |
| } | |
| }) | |
| assertEquals(66, makeS(66, 111).useContents { x }) | |
| } | |
| fun testVarargs() { | |
| assertEquals(E.ONE, makeE(1)) | |
| getVarargs( | |
| 0, | |
| true, | |
| 2.toByte(), | |
| Short.MIN_VALUE, | |
| 42, | |
| Long.MAX_VALUE, | |
| 3.14f, | |
| 2.71, | |
| 0x1234ABCDL.toCPointer<COpaque>(), | |
| UByte.MAX_VALUE, | |
| 22.toUShort(), | |
| 111u, | |
| ULong.MAX_VALUE, | |
| E.TWO, | |
| cValue<S> { x = 15 }, | |
| null | |
| ).useContents { | |
| assertEquals(1, a1) | |
| assertEquals(2.toByte(), a2) | |
| assertEquals(Short.MIN_VALUE, a3) | |
| assertEquals(42, a4) | |
| assertEquals(Long.MAX_VALUE, a5) | |
| assertEquals(3.14f, a6) | |
| assertEquals(2.71, a7) | |
| assertEquals(0x1234ABCDL, a8.toLong()) | |
| assertEquals(UByte.MAX_VALUE, a9) | |
| assertEquals(22.toUShort(), a10) | |
| assertEquals(111u, a11) | |
| assertEquals(ULong.MAX_VALUE, a12) | |
| assertEquals(E.TWO, a13) | |
| assertEquals(15, a14.x) | |
| assertEquals(null, a15) | |
| } | |
| } | |
| fun testCallableReferences() { | |
| val sumRef = ::sum | |
| assertEquals(3, sumRef(1, 2)) | |
| val sumPtr = staticCFunction(::sum) | |
| assertEquals(7, sumPtr(3, 4)) | |
| val anonymousFunPtr = staticCFunction(fun (x: Int, y: Int): Int { return x + y }) | |
| assertEquals(11, anonymousFunPtr(5, 6)) | |
| } |