Edit Page

Mapping Primitive Data Types from C

Last Updated 23 July 2018
Primitive Data types from C and how they look in Kotlin/Native

In this tutorial, we learn what C data types are visible in Kotlin/Native and vice versa. We will:

Types in C Language

What types do we have in the C language? Let's first list all of them. I have used the C data types article from Wikipedia as a basis. There are following types in the C programming language:

  • basic types char, int, float, double with modifiers signed, unsigned, short, long
  • structures, unions, arrays
  • pointers
  • function pointers

There are also more specific types:

  • boolean type (from C99)
  • size_t and ptrdiff_t (also ssize_t)
  • fixed width integer types, e.g., int32_t or uint64_t (from C99)

There are also the following type qualifiers in the C language: const, volatile, restruct, atomic.

The best way to see what C data types are visible in Kotlin is to try it

An Example C Library

We create a lib.h file to see how C functions are mapped into Kotlin:

#ifndef LIB2_H_INCLUDED
#define LIB2_H_INCLUDED

void ints(char c, short d, int e, long f);
void uints(unsigned char c, unsigned short d, unsigned int e, unsigned long f);
void doubles(float a, double b);

#endif

The file is missing the extern "C" block, which is not needed for our example, but may be necessary if we use C++ and overloaded functions. The C++ compatibility thread contains more details on this.

It is only necessary to have a .h file to run the cinterop tool. And we do not need to create a lib.c file, unless we want to compile and run the example.

We still need to create a .def file to the cinterop. More details on this are covered in the Interop with C Libraries tutorial. the tutorial to create the lib.def file with the following content:

headers = lib.h

We could have avoided creating the .h file and placed declarations directly to the .def file. This is what we do in the next tutorial.

Inspecting Generated Kotlin APIs for a C library

We need to have a Kotlin compiler on our machines. There is the A Basic Kotlin Application that covers this in a more detail. Let's assume we have a console, where the kotlinc-native, cinterop, and klib commands are available.

Now we are ready to compile the library and to import it into Kotlin. Let's call the following commands:

cinterop -def lib.def -compilerOpts "-I." -o lib.klib
klib contents lib.klib

The cinterop command generates the lib.klib, the Kotlin library, which is the bridge to call C code. The klib command prints the API of the library to the console.

Primitive Types in Kotlin

From cinterop and klib calls we see the following API:

fun doubles(a: Float, b: Double)
fun uints(c: UByte, d: UShort, e: UInt, f: ULong)
fun ints(c: Byte, d: Short, e: Int, f: Long)

C types are mapped in the way we would expect, note that char type is mapped to kotlin.Byte as it is usually an 8-bit signed value.

C Kotlin
char kotlin.Byte
unsigned char kotlin.UByte
short kotlin.Short
unsigned short kotlin.UShort
int kotlin.Int
unsigned int kotlin.UInt
long long kotlin.Long
unsigned long long kotlin.ULong
float kotlin.Float
double kotlin.Double

Next Steps

We will continue to explore more complicated C language types and their representation in Kotlin/Native in the next tutorials:

The C Interop documentation documentation covers more advanced scenarios of the interop.