Mapping primitive data types from C – tutorial
In this tutorial, you will learn what C data types are visible in Kotlin/Native and vice versa. You will:
See what Data types are in C language.
Create a tiny C Library that uses those types in exports.
Find how Primitive types in Kotlin are mapped to C.
Types in C language
What types are there in the C language? Let's take the C data types article from Wikipedia as a basis. There are following types in the C programming language:
char, int, float, doublewith modifiers
signed, unsigned, short, long
structures, unions, arrays
There are also more specific types:
boolean type (from C99)
fixed width integer types, such as
There are also the following type qualifiers in the C language:
The best way to see what C data types are visible in Kotlin is to try it.
Example C library
lib.h file to see how C functions are mapped into Kotlin:
The file is missing the
extern "C" block, which is not needed for this example, but may be necessary if you use C++ and overloaded functions. The C++ compatibility thread on Stackoverflow contains more details on this.
For every set of
.h files, you will be using the
cinterop tool from Kotlin/Native to generate a Kotlin/Native library, or
.klib. The generated library will bridge calls from Kotlin/Native to C. It includes respective Kotlin declarations for the definitions form the
.h files. It is only necessary to have a
.h file to run the
cinterop tool. And you do not need to create a
lib.c file, unless you want to compile and run the example. More details on this are covered in the C interop page. It is enough for the tutorial to create the
lib.def file with the following content:
You may include all declarations directly into the
.def file after a
--- separator. It can be helpful to include macros or other C defines into the code generated by the
cinterop tool. Method bodies are compiled and fully included into the binary too. Use that feature to have a runnable example without a need for a C compiler. To implement that, you need to add implementations to the C functions from the
lib.h file, and place these functions into a
.def file. You will have the following
interop.def file is enough to compile and run the application or open it in an IDE. Now it is time to create project files, open the project in IntelliJ IDEA and run it.
Inspect generated Kotlin APIs for a C library
While it is possible to use the command line, either directly or by combining it with a script file (such as
.bat file), this approach doesn't scale well for big projects that have hundreds of files and libraries. It is then better to use the Kotlin/Native compiler with a build system, as it helps to download and cache the Kotlin/Native compiler binaries and libraries with transitive dependencies and run the compiler and tests. Kotlin/Native can use the Gradle build system through the kotlin-multiplatform plugin.
We covered the basics of setting up an IDE compatible project with Gradle in the A Basic Kotlin/Native Application tutorial. Please check it out if you are looking for detailed first steps and instructions on how to start a new Kotlin/Native project and open it in IntelliJ IDEA. In this tutorial, we'll look at the advanced C interop related usages of Kotlin/Native and multiplatform builds with Gradle.
First, create a project folder. All the paths in this tutorial will be relative to this folder. Sometimes the missing directories will have to be created before any new files can be added.
Use the following
build.gradle(.kts) Gradle build file:
The project file configures the C interop as an additional step of the build. Let's move the
interop.def file to the
src/nativeInterop/cinterop directory. Gradle recommends using conventions instead of configurations, for example, the source files are expected to be in the
src/nativeMain/kotlin folder. By default, all the symbols from C are imported to the
interop package, you may want to import the whole package in our
.kt files. Check out the kotlin-multiplatform plugin documentation to learn about all the different ways you could configure it.
src/nativeMain/kotlin/hello.kt stub file with the following content to see how C primitive type declarations are visible from Kotlin:
Now you are ready to open the project in IntelliJ IDEA and to see how to fix the example project. While doing that, see how C primitive types are mapped into Kotlin/Native.
Primitive types in kotlin
With the help of IntelliJ IDEA's Go to | Declaration or compiler errors, you see the following generated API for the C functions:
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.
|unsigned long long||kotlin.ULong|
Fix the code
You've seen all definitions and it is the time to fix the code. Run the
runDebugExecutableNative Gradle task in IDE or use the following command to run the code:
The final code in the
hello.kt file may look like that:
Continue to explore more complicated C language types and their representation in Kotlin/Native in the next tutorials:
The C interop documentation covers more advanced scenarios of the interop.