[K/N] Move cinterop tests from standalone to codegen/box
^KT-61259
This commit is contained in:
committed by
Space Team
parent
0b0ba3160f
commit
c09e8909d4
@@ -0,0 +1,34 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: carrayPointers.def
|
||||
---
|
||||
int (*arrayPointer)[1];
|
||||
|
||||
int globalArray[3] = {1, 2, 3};
|
||||
|
||||
struct StructWithArrayPtr {
|
||||
int (*arrayPointer)[1];
|
||||
};
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import carrayPointers.*
|
||||
import kotlin.test.*
|
||||
import kotlinx.cinterop.*
|
||||
|
||||
fun box(): String {
|
||||
arrayPointer = globalArray
|
||||
assertEquals(globalArray[0], arrayPointer!![0])
|
||||
arrayPointer!![0] = 15
|
||||
assertEquals(15, globalArray[0])
|
||||
|
||||
memScoped {
|
||||
val struct = alloc<StructWithArrayPtr>()
|
||||
struct.arrayPointer = globalArray
|
||||
assertEquals(globalArray[0], struct.arrayPointer!![0])
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// FREE_CINTEROP_ARGS: -header auxiliaryCppSources.h
|
||||
|
||||
// MODULE: cinterop
|
||||
// FILE: auxiliaryCppSources.def
|
||||
# The def file is intentionally empty
|
||||
# `auxiliaryCppSources.h` is meant to be included via `-header` free arg of cinterop tool
|
||||
|
||||
// FILE: auxiliaryCppSources.h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char* name();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// FILE: auxiliaryCppSources.cpp
|
||||
#include <string>
|
||||
#include "auxiliaryCppSources.h"
|
||||
|
||||
static std::string _name = "OK";
|
||||
|
||||
const char* name() {
|
||||
return _name.c_str();
|
||||
}
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import auxiliaryCppSources.*
|
||||
import kotlin.test.*
|
||||
import kotlinx.cinterop.*
|
||||
|
||||
fun box(): String {
|
||||
return name()!!.toKString()
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// May need disabling when gcSchedulerType=aggressive . since it may be too slow
|
||||
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: bitfields.def
|
||||
---
|
||||
enum B2 {
|
||||
ZERO, ONE, TWO, THREE
|
||||
};
|
||||
|
||||
enum E : short {
|
||||
A, B
|
||||
};
|
||||
|
||||
struct __attribute__((packed)) S {
|
||||
long long x1 : 1;
|
||||
enum B2 x2 : 2;
|
||||
unsigned short x3 : 3;
|
||||
unsigned int x4 : 4;
|
||||
int x5 : 5;
|
||||
long long x6 : 63;
|
||||
enum E x7: 2;
|
||||
_Bool x8 : 1;
|
||||
struct { int x9:4; };
|
||||
};
|
||||
|
||||
static long long getX1(struct S* s) { return s->x1; }
|
||||
static enum B2 getX2(struct S* s) { return s->x2; }
|
||||
static unsigned short getX3(struct S* s) { return s->x3; }
|
||||
static unsigned int getX4(struct S* s) { return s->x4; }
|
||||
static int getX5(struct S* s) { return s->x5; }
|
||||
static long long getX6(struct S* s) { return s->x6; }
|
||||
static enum E getX7(struct S* s) { return s->x7; }
|
||||
static _Bool getX8(struct S* s) { return s->x8; }
|
||||
static int getX9(struct S* s) { return s->x9; }
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import bitfields.*
|
||||
import kotlinx.cinterop.*
|
||||
|
||||
fun assertEquals(value1: Any?, value2: Any?) {
|
||||
if (value1 != value2)
|
||||
throw AssertionError("Expected $value1, got $value2")
|
||||
}
|
||||
|
||||
fun check(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean, x9: Int) {
|
||||
assertEquals(x1, s.x1)
|
||||
assertEquals(x1, getX1(s.ptr))
|
||||
|
||||
assertEquals(x2, s.x2)
|
||||
assertEquals(x2, getX2(s.ptr))
|
||||
|
||||
assertEquals(x3, s.x3)
|
||||
assertEquals(x3, getX3(s.ptr))
|
||||
|
||||
assertEquals(x4, s.x4)
|
||||
assertEquals(x4, getX4(s.ptr))
|
||||
|
||||
assertEquals(x5, s.x5)
|
||||
assertEquals(x5, getX5(s.ptr))
|
||||
|
||||
assertEquals(x6, s.x6)
|
||||
assertEquals(x6, getX6(s.ptr))
|
||||
|
||||
assertEquals(x7, s.x7)
|
||||
assertEquals(x7, getX7(s.ptr))
|
||||
|
||||
assertEquals(x8, s.x8)
|
||||
assertEquals(x8, getX8(s.ptr))
|
||||
|
||||
assertEquals(x9, s.x9)
|
||||
assertEquals(x9, getX9(s.ptr))
|
||||
}
|
||||
|
||||
fun assign(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean, x9: Int) {
|
||||
s.x1 = x1
|
||||
s.x2 = x2
|
||||
s.x3 = x3
|
||||
s.x4 = x4
|
||||
s.x5 = x5
|
||||
s.x6 = x6
|
||||
s.x7 = x7
|
||||
s.x8 = x8
|
||||
s.x9 = x9
|
||||
}
|
||||
|
||||
fun assignReversed(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean, x9: Int) {
|
||||
s.x9 = x9
|
||||
s.x8 = x8
|
||||
s.x7 = x7
|
||||
s.x6 = x6
|
||||
s.x5 = x5
|
||||
s.x4 = x4
|
||||
s.x3 = x3
|
||||
s.x2 = x2
|
||||
s.x1 = x1
|
||||
}
|
||||
|
||||
fun test(s: S, x1: Long, x2: B2, x3: UShort, x4: UInt, x5: Int, x6: Long, x7: E, x8: Boolean, x9: Int) {
|
||||
assign(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
||||
check(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
||||
|
||||
assignReversed(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
||||
check(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
||||
|
||||
// Also check with some insignificant bits modified:
|
||||
|
||||
assign(s, x1 + 2, x2, (x3 + 8u).toUShort(), x4 - 16u, x5 + 32, x6 + Long.MIN_VALUE, x7, x8, x9 + 16)
|
||||
check(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
||||
|
||||
assignReversed(s, x1 + 2, x2, (x3 + 8u).toUShort(), x4 - 16u, x5 + 32, x6 + Long.MIN_VALUE, x7, x8, x9 + 16)
|
||||
check(s, x1, x2, x3, x4, x5, x6, x7, x8, x9)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
memScoped {
|
||||
val s = alloc<S>()
|
||||
for (x1 in -1L..0L)
|
||||
for (x2 in arrayOf(B2.ZERO, B2.ONE, B2.THREE))
|
||||
for (x3 in ushortArrayOf(0u, 2u, 7u))
|
||||
for (x4 in uintArrayOf(0u, 6u, 15u))
|
||||
for (x5 in intArrayOf(-16, -1, 0, 5, 15))
|
||||
for (x6 in longArrayOf(Long.MIN_VALUE/2, -325L, 0, 1L shl 48, Long.MAX_VALUE/2))
|
||||
for (x7 in E.values())
|
||||
for (x8 in arrayOf(false, true))
|
||||
for (x9 in intArrayOf(-8, -1, 0, 5, 7)) // 4 bits width
|
||||
test(s, x1, x2, x3.toUShort(), x4, x5, x6, x7, x8, x9)
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// 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 })
|
||||
})
|
||||
|
||||
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))
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: cenums.def
|
||||
---
|
||||
enum E {
|
||||
A, B, C
|
||||
};
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
// !LANGUAGE: +EnumEntries
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import cenums.*
|
||||
import kotlinx.cinterop.*
|
||||
import kotlin.test.*
|
||||
|
||||
@OptIn(kotlin.ExperimentalStdlibApi::class)
|
||||
fun box(): String {
|
||||
memScoped {
|
||||
val e = alloc<E.Var>()
|
||||
e.value = E.C
|
||||
assertEquals(E.C, e.value)
|
||||
|
||||
assertFailsWith<NotImplementedError> {
|
||||
e.value = TODO()
|
||||
}
|
||||
}
|
||||
val values = E.values()
|
||||
assertEquals(values[0], E.A)
|
||||
assertEquals(values[1], E.B)
|
||||
assertEquals(values[2], E.C)
|
||||
// TODO: temporariry commented. Task for investigation is KT-56107
|
||||
// val entries = E.entries
|
||||
// assertEquals(entries[0], E.A)
|
||||
// assertEquals(entries[1], E.B)
|
||||
// assertEquals(entries[2], E.C)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// This test mostly checks frontend behaviour.
|
||||
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: cForwardDeclarations.def
|
||||
---
|
||||
struct StructDeclared;
|
||||
struct StructDefined { int x; };
|
||||
|
||||
int useStructDeclared(struct StructDeclared* declared) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int useStructDefined(struct StructDefined* defined) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import cForwardDeclarations.*
|
||||
import cnames.structs.StructDeclared
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
import kotlinx.cinterop.COpaque
|
||||
import kotlinx.cinterop.CStructVar
|
||||
import kotlinx.cinterop.ptr
|
||||
// The test should also check that these references can't be resolved, but the test infra doesn't support this yet:
|
||||
// import cForwardDeclarations.StructUndeclared
|
||||
// import cnames.structs.StructUndeclared // Supported in K1 though.
|
||||
|
||||
fun <T1 : T2, T2> checkSubtype2() {}
|
||||
|
||||
// Here we rely on frontend reporting conflicting overloads if some of these types turn out to be the same.
|
||||
fun checkDifferentTypes(s: StructDeclared?) = 1
|
||||
fun checkDifferentTypes(s: StructDefined?) = 2
|
||||
|
||||
fun box(): String {
|
||||
checkSubtype2<StructDeclared, COpaque>()
|
||||
|
||||
checkSubtype2<StructDefined, CStructVar>()
|
||||
|
||||
val declared: StructDeclared? = null
|
||||
val defined: StructDefined? = null
|
||||
|
||||
assertEquals(1, checkDifferentTypes(declared))
|
||||
assertEquals(2, checkDifferentTypes(defined))
|
||||
|
||||
assertEquals(-1, useStructDeclared(declared?.ptr))
|
||||
assertEquals(-2, useStructDefined(defined?.ptr))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// OUTPUT_DATA_FILE: funptr.out
|
||||
// MODULE: cinterop
|
||||
// FILE: cfunptr.def
|
||||
headerFilter = NOTHING
|
||||
---
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int (*atoiPtrType)(const char*);
|
||||
|
||||
static atoiPtrType getAtoiPtr() {
|
||||
return &atoi;
|
||||
}
|
||||
|
||||
static void __printInt(int x) {
|
||||
printf("%d\n", x);
|
||||
}
|
||||
|
||||
static void* __getPrintIntPtr() {
|
||||
return &__printInt;
|
||||
}
|
||||
|
||||
typedef void* (*getPrintIntPtrPtrType)(void);
|
||||
|
||||
static getPrintIntPtrPtrType getGetPrintIntPtrPtr() {
|
||||
return &__getPrintIntPtr;
|
||||
}
|
||||
|
||||
static double __add(double x, double y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
typedef double (*addPtrType)(double, double);
|
||||
|
||||
static addPtrType getAddPtr() {
|
||||
return &__add;
|
||||
}
|
||||
|
||||
static int __doubleToInt(double x) {
|
||||
return (int) x;
|
||||
}
|
||||
|
||||
typedef int (*doubleToIntPtrType)(double);
|
||||
|
||||
static doubleToIntPtrType getDoubleToIntPtr() {
|
||||
return &__doubleToInt;
|
||||
}
|
||||
|
||||
static _Bool __isIntPositive(int x) {
|
||||
return x > 0;
|
||||
}
|
||||
|
||||
typedef _Bool (*isIntPositivePtrType)(int);
|
||||
|
||||
static isIntPositivePtrType getIsIntPositivePtr() {
|
||||
return &__isIntPositive;
|
||||
}
|
||||
|
||||
static unsigned int getMaxUInt(void) {
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
static typeof(&getMaxUInt) getMaxUIntGetter() {
|
||||
return &getMaxUInt;
|
||||
}
|
||||
|
||||
typedef int (*longSignatureFunctionPtrType)(
|
||||
int, int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int
|
||||
);
|
||||
|
||||
typedef int (*notSoLongSignatureFunctionPtrType)(
|
||||
int, int, int, int, int, int, int, int, int, int, int,
|
||||
int, int, int, int, int, int, int, int, int, int, int
|
||||
);
|
||||
|
||||
static int longSignatureFunction(
|
||||
int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11, int p12,
|
||||
int p13, int p14, int p15, int p16, int p17, int p18, int p19, int p20, int p21, int p22, int p23
|
||||
) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
static int notSoLongSignatureFunction(
|
||||
int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11, int p12,
|
||||
int p13, int p14, int p15, int p16, int p17, int p18, int p19, int p20, int p21, int p22
|
||||
) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
static longSignatureFunctionPtrType getLongSignatureFunctionPtr() {
|
||||
return &longSignatureFunction;
|
||||
}
|
||||
|
||||
static notSoLongSignatureFunctionPtrType getNotSoLongSignatureFunctionPtr() {
|
||||
return ¬SoLongSignatureFunction;
|
||||
}
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import cfunptr.*
|
||||
import kotlin.test.*
|
||||
|
||||
typealias NotSoLongSignatureFunction = (
|
||||
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
|
||||
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int
|
||||
) -> Int
|
||||
|
||||
fun box(): String {
|
||||
val atoiPtr = getAtoiPtr()!!
|
||||
|
||||
val getPrintIntPtrPtr = getGetPrintIntPtrPtr()!!
|
||||
val printIntPtr = getPrintIntPtrPtr()!!.reinterpret<CFunction<(Int) -> Unit>>()
|
||||
|
||||
val fortyTwo = memScoped {
|
||||
atoiPtr("42".cstr.getPointer(memScope))
|
||||
}
|
||||
|
||||
printIntPtr(fortyTwo)
|
||||
|
||||
printIntPtr(
|
||||
getDoubleToIntPtr()!!(
|
||||
getAddPtr()!!(5.1, 12.2)
|
||||
)
|
||||
)
|
||||
|
||||
val isIntPositivePtr = getIsIntPositivePtr()!!
|
||||
|
||||
printIntPtr(isIntPositivePtr(42).ifThenOneElseZero())
|
||||
printIntPtr(isIntPositivePtr(-42).ifThenOneElseZero())
|
||||
|
||||
assertEquals(getMaxUIntGetter()!!(), UInt.MAX_VALUE)
|
||||
|
||||
val longSignaturePtr: COpaquePointer? = getLongSignatureFunctionPtr()
|
||||
val notSoLongSignaturePtr: CPointer<CFunction<NotSoLongSignatureFunction>>? = getNotSoLongSignatureFunctionPtr()
|
||||
printIntPtr(notSoLongSignaturePtr!!.invoke(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
|
||||
printIntPtr(notSoLongSignatureFunction(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun Boolean.ifThenOneElseZero() = if (this) 1 else 0
|
||||
@@ -0,0 +1,6 @@
|
||||
42
|
||||
17
|
||||
1
|
||||
0
|
||||
42
|
||||
42
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: cglobals.def
|
||||
---
|
||||
const int g1 = 42;
|
||||
|
||||
int g2 = 17;
|
||||
|
||||
struct S {
|
||||
int x;
|
||||
} g3 = { 128 };
|
||||
|
||||
int g4[2] = { 13, 14 };
|
||||
|
||||
int g5[2][2] = { 15, 16, 17, 18 };
|
||||
|
||||
struct S* const g6 = &g3;
|
||||
|
||||
void globals_foo() {
|
||||
// Test that local vars are not treated as global ones.
|
||||
float g1;
|
||||
}
|
||||
|
||||
// Test non-compilable variable:
|
||||
typedef int MyInt;
|
||||
MyInt g7;
|
||||
#define g7 bad macro
|
||||
|
||||
// Test property name mangling:
|
||||
struct g1 {};
|
||||
struct g1_ {};
|
||||
|
||||
typedef void* voidptr;
|
||||
_Pragma("clang assume_nonnull begin")
|
||||
const voidptr g8 = 0x1, g9 = 0x2;
|
||||
_Pragma("clang assume_nonnull end")
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalNativeApi::class)
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import cglobals.*
|
||||
|
||||
fun box(): String {
|
||||
assert(g1__ == 42)
|
||||
|
||||
assert(g2 == 17)
|
||||
g2 = 42
|
||||
assert(g2 == 42)
|
||||
|
||||
assert(g3.x == 128)
|
||||
g3.x = 7
|
||||
assert(g3.x == 7)
|
||||
|
||||
assert(g4[1] == 14)
|
||||
g4[1] = 15
|
||||
assert(g4[1] == 15)
|
||||
|
||||
assert(g5[0] == 15)
|
||||
assert(g5[3] == 18)
|
||||
g5[0] = 16
|
||||
assert(g5[0] == 16)
|
||||
|
||||
assert(g6 == g3.ptr)
|
||||
|
||||
assert(g8.toLong() == 0x1L)
|
||||
assert(g9.toLong() == 0x2L)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// FREE_CINTEROP_ARGS: -header incompleteTypes.h
|
||||
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: incompleteTypes.def
|
||||
# The def file is intentionally empty
|
||||
# `incompleteTypes.h` is meant to be included via `-header` option of cinterop tool
|
||||
|
||||
// FILE: incompleteTypes.h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Forward declaration.
|
||||
struct S;
|
||||
extern struct S s;
|
||||
|
||||
const char* getContent(struct S* s);
|
||||
void setContent(struct S* s, const char* name);
|
||||
|
||||
union U;
|
||||
extern union U u;
|
||||
|
||||
double getDouble(union U* u);
|
||||
void setDouble(union U* u, double value);
|
||||
|
||||
// Global array of unknown size.
|
||||
extern char array[];
|
||||
|
||||
|
||||
int arrayLength();
|
||||
void setArrayValue(char* array, char value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// FILE: incompleteTypes.cpp
|
||||
#include <string>
|
||||
#include "incompleteTypes.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct S {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
S s = {
|
||||
.name = "initial"
|
||||
};
|
||||
|
||||
void setContent(struct S* s, const char* name) {
|
||||
// Note that copy here is intentional: we use it as a workaround
|
||||
// for short lifetime of copy of the passed Kotlin string.
|
||||
s->name = name;
|
||||
}
|
||||
|
||||
const char* getContent(struct S* s) {
|
||||
return s->name.c_str();
|
||||
}
|
||||
|
||||
union U {
|
||||
float f;
|
||||
double d;
|
||||
};
|
||||
|
||||
void setDouble(union U* u, double value) {
|
||||
u->d = value;
|
||||
}
|
||||
|
||||
double getDouble(union U* u) {
|
||||
return u->d;
|
||||
}
|
||||
|
||||
union U u = {
|
||||
.d = 0.0
|
||||
};
|
||||
|
||||
char array[5] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
void setArrayValue(char* array, char value) {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
int arrayLength() {
|
||||
return sizeof(array) / sizeof(char);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import incompleteTypes.*
|
||||
import kotlinx.cinterop.*
|
||||
import kotlin.test.*
|
||||
|
||||
fun box(): String {
|
||||
assertNotNull(s.ptr)
|
||||
assertNotNull(u.ptr)
|
||||
assertNotNull(array)
|
||||
|
||||
assertEquals("initial", getContent(s.ptr)?.toKString())
|
||||
setContent(s.ptr, "yo")
|
||||
val ptr = getContent(s.ptr)
|
||||
assertEquals("yo", ptr?.toKString())
|
||||
|
||||
assertEquals(0.0, getDouble(u.ptr))
|
||||
setDouble(u.ptr, Double.MIN_VALUE)
|
||||
assertEquals(Double.MIN_VALUE, getDouble(u.ptr))
|
||||
|
||||
for (i in 0 until arrayLength()) {
|
||||
assertEquals(0x0, array[i])
|
||||
}
|
||||
setArrayValue(array, 0x1)
|
||||
for (i in 0 until arrayLength()) {
|
||||
assertEquals(0x1, array[i])
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: kt43265.def
|
||||
strictEnums = bcm2835FunctionSelect
|
||||
---
|
||||
enum bcm2835FunctionSelect {
|
||||
BCM2835_GPIO_FSEL_INPT = 0x00, BCM2835_GPIO_FSEL_OUTP = 0x01, BCM2835_GPIO_FSEL_ALT0 = 0x04, BCM2835_GPIO_FSEL_ALT1 = 0x05,
|
||||
BCM2835_GPIO_FSEL_ALT2 = 0x06, BCM2835_GPIO_FSEL_ALT3 = 0x07, BCM2835_GPIO_FSEL_ALT4 = 0x03, BCM2835_GPIO_FSEL_ALT5 = 0x02,
|
||||
BCM2835_GPIO_FSEL_MASK = 0x07
|
||||
};
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
import kt43265.*
|
||||
import kotlin.test.*
|
||||
|
||||
@kotlinx.cinterop.ExperimentalForeignApi
|
||||
fun box(): String {
|
||||
assertEquals(bcm2835FunctionSelect.BCM2835_GPIO_FSEL_ALT3, bcm2835FunctionSelect.BCM2835_GPIO_FSEL_MASK)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: kt44283.def
|
||||
---
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef struct {
|
||||
int d;
|
||||
} TestStruct;
|
||||
|
||||
typedef struct {
|
||||
void (*f)(TestStruct data);
|
||||
} ThreadData;
|
||||
|
||||
void *dispatch(void *rawArg) {
|
||||
ThreadData *arg = rawArg;
|
||||
arg->f((TestStruct) {.d = 1});
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void invokeFromThread(void (*f)(TestStruct data)) {
|
||||
pthread_t thread_id;
|
||||
ThreadData *threadData = malloc(sizeof(ThreadData));
|
||||
threadData->f = f;
|
||||
pthread_create(&thread_id, NULL, dispatch, (void *) threadData);
|
||||
pthread_join(thread_id, NULL);
|
||||
}
|
||||
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import kt44283.*
|
||||
import kotlin.concurrent.AtomicInt
|
||||
import kotlin.test.*
|
||||
|
||||
val callbackCounter = AtomicInt(0)
|
||||
|
||||
@ExperimentalForeignApi
|
||||
fun box(): String {
|
||||
val func = staticCFunction<CValue<TestStruct>, Unit> {
|
||||
kotlin.native.runtime.GC.collect() // Helps to ensure that "runtime" is already initialized.
|
||||
|
||||
memScoped {
|
||||
println("Hello, Kotlin/Native! ${it.ptr.pointed.d}")
|
||||
}
|
||||
callbackCounter.incrementAndGet()
|
||||
}
|
||||
|
||||
assertEquals(0, callbackCounter.value)
|
||||
invokeFromThread(func.reinterpret())
|
||||
assertEquals(1, callbackCounter.value)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: kt54284.def
|
||||
---
|
||||
#define KFILE "FILE:" __FILE__
|
||||
#define KLINE "LINE:" __LINE__
|
||||
#define KTIME "TIME:" __TIME__
|
||||
#define KDATE "DATE:" __DATE__
|
||||
#define KFILENAME "NAME:" __FILE_NAME__
|
||||
#define KBASEFILE "BASE:" __BASE_FILE__
|
||||
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import kt54284.*
|
||||
import kotlin.test.*
|
||||
|
||||
@ExperimentalForeignApi
|
||||
fun box(): String {
|
||||
assertEquals("FILE:__FILE__", KFILE)
|
||||
assertEquals("LINE:__LINE__", KLINE)
|
||||
assertEquals("TIME:__TIME__", KTIME)
|
||||
assertEquals("DATE:__DATE__", KDATE)
|
||||
assertEquals("NAME:__FILE_NAME__", KFILENAME)
|
||||
assertEquals("BASE:__BASE_FILE__", KBASEFILE)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: kt54284_fmodules.def
|
||||
compilerOpts = -fmodules
|
||||
---
|
||||
#define KFILE "FILE:" __FILE__
|
||||
#define KLINE "LINE:" __LINE__
|
||||
#define KTIME "TIME:" __TIME__
|
||||
#define KDATE "DATE:" __DATE__
|
||||
#define KFILENAME "NAME:" __FILE_NAME__
|
||||
#define KBASEFILE "BASE:" __BASE_FILE__
|
||||
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
import kotlinx.cinterop.*
|
||||
import kt54284_fmodules.*
|
||||
import kotlin.test.*
|
||||
|
||||
@ExperimentalForeignApi
|
||||
fun box(): String {
|
||||
assertEquals("FILE:__FILE__", KFILE)
|
||||
assertEquals("LINE:__LINE__", KLINE)
|
||||
assertEquals("TIME:__TIME__", KTIME)
|
||||
assertEquals("DATE:__DATE__", KDATE)
|
||||
assertEquals("NAME:__FILE_NAME__", KFILENAME)
|
||||
assertEquals("BASE:__BASE_FILE__", KBASEFILE)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: kt63048.def
|
||||
language = Objective-C
|
||||
headers = kt63048.h
|
||||
|
||||
// FILE: kt63048.h
|
||||
#import "Foundation/NSString.h"
|
||||
#import "Foundation/NSObject.h"
|
||||
|
||||
@interface WithClassProperty : NSObject
|
||||
-(instancetype) init;
|
||||
@property (class, readonly, copy) NSString * stringProperty;
|
||||
@end
|
||||
|
||||
|
||||
// FILE: kt63048.m
|
||||
#import "kt63048.h"
|
||||
|
||||
@implementation WithClassProperty : NSObject
|
||||
-(instancetype) init {}
|
||||
+ (NSString *) stringProperty { return @"153"; }
|
||||
@end
|
||||
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class, kotlin.experimental.ExperimentalObjCName::class)
|
||||
|
||||
import kt63048.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ObjCName("KotlinImplWithCompanionPropertyOverride")
|
||||
class Impl : WithClassProperty() {
|
||||
companion object : WithClassPropertyMeta() {
|
||||
override fun stringProperty(): String? = "42"
|
||||
}
|
||||
}
|
||||
|
||||
@ObjCName("KotlinImplWithoutCompanionPropertyOverride")
|
||||
class ImplWithoutOverride : WithClassProperty() {
|
||||
companion object : WithClassPropertyMeta() {
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("42", Impl.stringProperty())
|
||||
assertEquals("153", ImplWithoutOverride.stringProperty())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: leakMemoryWithRunningThreadUnchecked.def
|
||||
---
|
||||
void test_RunInNewThread(void (*)());
|
||||
|
||||
// FILE: leakMemoryWithRunningThreadUnchecked.h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void test_RunInNewThread(void (*)());
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// FILE: leakMemoryWithRunningThreadUnchecked.cpp
|
||||
#include "leakMemoryWithRunningThreadUnchecked.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
extern "C" void test_RunInNewThread(void (*f)()) {
|
||||
std::atomic<bool> haveRun(false);
|
||||
std::thread t([f, &haveRun]() {
|
||||
f();
|
||||
haveRun = true;
|
||||
while (true) {}
|
||||
});
|
||||
t.detach();
|
||||
while (!haveRun) {}
|
||||
}
|
||||
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
@file:OptIn(
|
||||
kotlin.experimental.ExperimentalNativeApi::class,
|
||||
kotlin.native.runtime.NativeRuntimeApi::class,
|
||||
kotlinx.cinterop.ExperimentalForeignApi::class
|
||||
)
|
||||
|
||||
import leakMemoryWithRunningThreadUnchecked.*
|
||||
import kotlin.concurrent.AtomicInt
|
||||
import kotlin.native.concurrent.*
|
||||
import kotlin.native.Platform
|
||||
import kotlin.test.*
|
||||
import kotlinx.cinterop.*
|
||||
|
||||
val global = AtomicInt(0)
|
||||
|
||||
fun ensureInititalized() {
|
||||
// Only needed with the legacy MM. TODO: Remove when legacy MM is gone.
|
||||
kotlin.native.initRuntimeIfNeeded()
|
||||
// Leak memory
|
||||
StableRef.create(Any())
|
||||
global.value = 1
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
Platform.isMemoryLeakCheckerActive = true
|
||||
kotlin.native.runtime.Debugging.forceCheckedShutdown = false
|
||||
assertTrue(global.value == 0)
|
||||
// Created a thread, made sure Kotlin is initialized there.
|
||||
test_RunInNewThread(staticCFunction(::ensureInititalized))
|
||||
assertTrue(global.value == 1)
|
||||
// Now exiting. With unchecked shutdown, we exit quietly, even though there're
|
||||
// unfinished threads with runtimes.
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// TARGET_BACKEND: NATIVE
|
||||
// MODULE: cinterop
|
||||
// FILE: toKString.def
|
||||
---
|
||||
const char* empty() { return ""; }
|
||||
const char* foo() { return "foo"; }
|
||||
const char* kuku() { return "куку"; }
|
||||
const char* invalid_utf8() { return "\x85\xAF"; }
|
||||
const char* zero_in_the_middle() { return "before zero\0after zero"; }
|
||||
|
||||
|
||||
// MODULE: main(cinterop)
|
||||
// FILE: main.kt
|
||||
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
|
||||
|
||||
import toKString.*
|
||||
import kotlinx.cinterop.*
|
||||
import kotlin.native.*
|
||||
import kotlin.test.*
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("", empty()!!.toKStringFromUtf8())
|
||||
assertEquals("foo", foo()!!.toKStringFromUtf8())
|
||||
assertEquals("куку", kuku()!!.toKStringFromUtf8())
|
||||
assertEquals("\uFFFD\uFFFD", invalid_utf8()!!.toKStringFromUtf8())
|
||||
assertEquals("before zero", zero_in_the_middle()!!.toKStringFromUtf8())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user