[K/N] Treat DEF files as regular test source, compiled with cinterop

^KT-61259
This commit is contained in:
Vladimir Sukharev
2023-12-05 00:36:00 +01:00
committed by Space Team
parent 2530cba82a
commit 0b0ba3160f
57 changed files with 988 additions and 934 deletions
@@ -1,8 +0,0 @@
---
int (*arrayPointer)[1];
int globalArray[3] = {1, 2, 3};
struct StructWithArrayPtr {
int (*arrayPointer)[1];
};
@@ -1,9 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
const char* name();
#ifdef __cplusplus
}
#endif
@@ -1,8 +0,0 @@
#include <string>
#include "auxiliarySources.aux.h"
static std::string _name = "Hello from C++";
const char* name() {
return _name.c_str();
}
@@ -1,2 +0,0 @@
# The def file is empty intentianally
# `auxiliarySources.aux.h` is meant to be included via `-header` option of cinterop tool
@@ -1,9 +0,0 @@
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import auxiliarySources.*
import kotlin.test.*
import kotlinx.cinterop.*
fun main() {
assertEquals(name()!!.toKString(), "Hello from C++")
}
@@ -1,30 +0,0 @@
---
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; }
@@ -1,78 +0,0 @@
---
#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;
}
@@ -1,4 +0,0 @@
---
enum E {
A, B, C
};
@@ -1,11 +0,0 @@
---
struct StructDeclared;
struct StructDefined { int x; };
int useStructDeclared(struct StructDeclared* declared) {
return -1;
}
int useStructDefined(struct StructDefined* defined) {
return -2;
}
@@ -1,94 +0,0 @@
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 &notSoLongSignatureFunction;
}
@@ -1,48 +0,0 @@
// OUT_DATA_FILE: funptr.out
/*
* 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.
*/
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import funptr.*
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 main(args: Array<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))
}
fun Boolean.ifThenOneElseZero() = if (this) 1 else 0
@@ -1,33 +0,0 @@
---
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 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")
@@ -1,27 +0,0 @@
#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
@@ -1,53 +0,0 @@
#include <string>
#include "incompleteTypes.aux.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);
}
}
@@ -1,2 +0,0 @@
# The def file is empty intentianally
# `incompleteTypes.aux.h` is meant to be included via `-header` option of cinterop tool
@@ -1,28 +0,0 @@
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import incompleteTypes.*
import kotlinx.cinterop.*
import kotlin.test.*
fun main() {
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])
}
}
@@ -1,7 +0,0 @@
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
};
@@ -1,7 +0,0 @@
import kt43265.*
import kotlin.test.*
@kotlinx.cinterop.ExperimentalForeignApi
fun main() {
assertEquals(bcm2835FunctionSelect.BCM2835_GPIO_FSEL_ALT3, bcm2835FunctionSelect.BCM2835_GPIO_FSEL_MASK)
}
@@ -1,25 +0,0 @@
---
#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);
}
@@ -1,7 +0,0 @@
---
#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__
@@ -1,8 +0,0 @@
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__
@@ -1,2 +0,0 @@
language = Objective-C
headers = kt63048.h
@@ -1,7 +0,0 @@
#import "Foundation/NSString.h"
#import "Foundation/NSObject.h"
@interface WithClassProperty : NSObject
-(instancetype) init;
@property (class, readonly, copy) NSString * stringProperty;
@end
@@ -1,6 +0,0 @@
#import "kt63048.h"
@implementation WithClassProperty : NSObject
-(instancetype) init {}
+ (NSString *) stringProperty { return @"153"; }
@end
@@ -1,15 +0,0 @@
#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) {}
}
@@ -1,5 +0,0 @@
package leakMemoryWithRunningThreadUnchecked
---
void test_RunInNewThread(void (*)());
@@ -1,9 +0,0 @@
#ifdef __cplusplus
extern "C" {
#endif
void test_RunInNewThread(void (*)());
#ifdef __cplusplus
}
#endif
@@ -1,6 +0,0 @@
---
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"; }
@@ -1,6 +1,20 @@
// 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 arrayPointers.*
import carrayPointers.*
import kotlin.test.*
import kotlinx.cinterop.*
@@ -0,0 +1,40 @@
// 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 = "Hello from C++";
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 main() {
assertEquals(name()!!.toKString(), "Hello from C++")
}
@@ -4,6 +4,42 @@
*/
// May need disabling when gcSchedulerType=aggressive . since it may be too slow
// 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.*
@@ -2,11 +2,92 @@
* 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.
*/
// 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 callbacksAndVarargs.*
import ccallbacksAndVarargs.*
fun main() {
testStructCallbacks()
@@ -2,10 +2,20 @@
* 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.
*/
// 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 enums.*
import cenums.*
import kotlinx.cinterop.*
import kotlin.test.*
@@ -1,7 +1,26 @@
// This test mostly checks frontend behaviour.
// 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 forwardDeclarations.*
import cForwardDeclarations.*
import cnames.structs.StructDeclared
import kotlin.test.assertEquals
@@ -0,0 +1,149 @@
// OUTPUT_DATA_FILE: funptr.out
/*
* 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.
*/
// 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 &notSoLongSignatureFunction;
}
// 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 main(args: Array<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))
}
fun Boolean.ifThenOneElseZero() = if (this) 1 else 0
@@ -2,10 +2,50 @@
* 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.
*/
// 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 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 globals.*
import cglobals.*
fun main(args: Array<String>) {
assert(g1__ == 42)
@@ -0,0 +1,122 @@
// FREE_CINTEROP_ARGS: -header library.h
// MODULE: cinterop
// FILE: library.def
# The def file is intentionally empty
# `library.h` is meant to be included via `-header` option of cinterop tool
// FILE: library.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: library.cpp
#include <string>
#include "library.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 library.*
import kotlinx.cinterop.*
import kotlin.test.*
fun main() {
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])
}
}
@@ -0,0 +1,20 @@
// 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 main() {
assertEquals(bcm2835FunctionSelect.BCM2835_GPIO_FSEL_ALT3, bcm2835FunctionSelect.BCM2835_GPIO_FSEL_MASK)
}
@@ -1,3 +1,34 @@
// 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.*
@@ -1,3 +1,17 @@
// 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.*
@@ -1,3 +1,17 @@
// 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.*
@@ -1,3 +1,29 @@
// 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.*
@@ -1,3 +1,40 @@
// MODULE: cinterop
// FILE: leakMemoryWithRunningThreadUnchecked.def
package leakMemoryWithRunningThreadUnchecked
---
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,
@@ -1,3 +1,15 @@
// 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.*