The most trivial Kotlin/Native
example of using C
library
Some time ago I stuck linking a C binary into an executable with
___isOSVersionAtLeast is undefined.
And thus I decided to simplify things to localize the problem. I will write
a dedicated post with the solution for ___isOSVersionAtLeast is undefined
.
Let’s focus on the most trivial library example. To start with, I assume
you have Kotlin/Native
compiler in the OS Path. Have a look at
the main tutorial
or merely download the compiler from GitHub Releases page.
Beware, the compiler will download the toolchain on the very first run.
The konanc
and cinterop
tools should be in the PATH
of your terminal or console.
The rest of the post is created and tested on macOS. It should just work on Linux, but I did not check it. You shall have C/C++ toolchain installed too. On macOS, it is enough to install and run Xcode.
C Library
The lib.h
file looks as follows
The extern "C"
block is not needed (unless you use C++) and left here
for C++ compatibility.
Thus you may shrink the file to lib.h
:
#include guards
in your .h
files are a standard ritual. They are necessary for multiple .h
files projects.
The code above declares one function for export int foo()
. We use the .h
file later
with Kotlin/Native cinterop
tool import the function into Kotlin/Native.
Let’s create a lib.c
for implementation for the foo
function in C:
Now we compile the C sources into a C library. For that we call gcc
to compile (and link)
the .c
sources into a C static library:
It will be a bit more complicated if you have several .c
source files.
At that moment we have
lib.h
– the headerlib.c
– the implementationlib.o
– the intermediate object filelib.a
– the compiled static library
Importing to Kotlin/Native
We need to import the C library to be used with Kotlin/Native. It is as tricky as
calling a cinterop
tool.
The cinterop
tool uses the definition file for my library lib.def
:
The file helps to specify all necessary options for bigger libraries.
Not it is the time to call the cinterop
with the following options:
The result is a lib.klib
file. A Kotlin/Native library file. It contains Kotlin APIs for
our lib.h
. It bridges C types and Kotlin/Native types (trivial Int
in our case) and helps
to deal with memory management (not needed for our example).
At that moment we have
lib.h
– the headerlib.c
– the implementationlib.o
– the intermediate object filelib.a
– the compiled static librarylib.def
– the definitions forcinterop
, reference tolib.h
lib.klib
– the compiled Kotlin/Native library to access API fromlib.h
Compiling with Kotlin/Native
We need an entry point and Kotlin sources. I created the main.kt
file for that
And I compile it with the following command
and run the ./main.kexe
to see the resulting text is being printed:
./main.kexe
The foo() from lib.h returned 42
Conclusion
That is a trivial C library linking case. For something real, you’ll probably want to use Gradle build.
Take a look at the Interop with C libraries tutorial or the list of Platform libraries.
You may find it useful to check the C Interop docs or Interop with Swift and Objective-C page.
comments powered by Disqus