1
- [ // ] : # ( title: Create an app using C Interop and libcurl – tutorial )
1
+ [ // ] : # ( title: Create an app using C interop and libcurl – tutorial )
2
2
3
3
This tutorial demonstrates how to use IntelliJ IDEA to create a command-line application. You'll learn how to create
4
- a simple HTTP client that can run natively on specified platforms using Kotlin/Native and the ` libcurl ` library.
4
+ a simple HTTP client that can run natively on specified platforms using Kotlin/Native and the libcurl library.
5
5
6
6
The output will be an executable command-line app that you can run on macOS and Linux and make simple HTTP GET requests.
7
7
@@ -13,15 +13,19 @@ Kotlin/Native can use the [Gradle](https://gradle.org) build system through the
13
13
14
14
## Before you start
15
15
16
- 1 . Download and install the latest version of [ IntelliJ IDEA] ( https://www.jetbrains.com/idea/ ) with the latest [ Kotlin plugin ] ( releases.md ) .
16
+ 1 . Download and install the latest version of [ IntelliJ IDEA] ( https://www.jetbrains.com/idea/ ) .
17
17
2 . Clone the [ project template] ( https://github.com/Kotlin/kmp-native-wizard )
18
- by selecting ** File** | ** New** | ** Project from Version Control** in IntelliJ IDEA.
18
+ by selecting ** File** | ** New** | ** Project from Version Control** in IntelliJ IDEA and using this URL:
19
+
20
+ ``` none
21
+ https://github.com/Kotlin/kmp-native-wizard
22
+ ```
19
23
20
24
3 . Explore the project structure:
21
25
22
26
![ Native application project structure] ( native-project-structure.png ) {width=700}
23
27
24
- The template includes a project with the files and folders you need to get you started. It's important to understand
28
+ The template includes a project with the files and folders you need to get started. It's important to understand
25
29
that an application written in Kotlin/Native can target different platforms if the code does not have platform-specific
26
30
requirements. Your code is placed in the ` nativeMain ` directory with a corresponding ` nativeTest ` . For this tutorial,
27
31
keep the folder structure as is.
@@ -54,7 +58,7 @@ Kotlin/Native can use the [Gradle](https://gradle.org) build system through the
54
58
55
59
```
56
60
57
- * Targets are defined using `macosX64 `, `macosArm64 `, `linuxX64 `, `linuxArm64 `, and `mingwX64` for macOS, Linux ,
61
+ * Targets are defined using `macosArm64 `, `macosX64 `, `linuxArm64 `, `linuxX64 `, and `mingwX64` for macOS, Linux ,
58
62
and Windows . See the complete list of [supported platforms](native- target- support.md).
59
63
* The entry itself defines a series of properties to indicate how the binary is generated and the entry
60
64
point of the applications. These can be left as default values.
@@ -73,15 +77,17 @@ for pretty much anything you may need. Kotlin/Native is already shipped with a s
73
77
which provide some additional common functionality to the standard library.
74
78
75
79
An ideal scenario for interop is to call C functions as if you are calling Kotlin functions, following the same
76
- signature and conventions. This is when the ` cinterop` tool comes in handy. It takes a C library and generates the
80
+ signature and conventions. This is when the cinterop tool comes in handy. It takes a C library and generates the
77
81
corresponding Kotlin bindings, so that the library can be used as if it were Kotlin code.
78
82
79
- To generate these bindings, create a library definition `.def` file that contains some information about the necessary
80
- headers. In this app, you' ll need the `libcurl` library to make some HTTP calls. To create a definition file:
83
+ To generate these bindings, each library needs a definition file, usually with the same name as the library.
84
+ This is a property file that describes exactly how the library should be consumed.
85
+
86
+ In this app, you' ll need the libcurl library to make some HTTP calls. To create its definition file:
81
87
82
88
1. Select the `src` folder and create a new directory with **File | New | Directory**.
83
- 2. Name new directory **nativeInterop/cinterop**. This is the default convention for header file locations, though it can
84
- be overridden in the `build.gradle.kts` file if you use a different location.
89
+ 2. Name the new directory **nativeInterop/cinterop**. This is the default convention for header file locations,
90
+ though it can be overridden in the `build.gradle.kts` file if you use a different location.
85
91
3. Select this new subfolder and create a new `libcurl.def` file with **File | New | File**.
86
92
4. Update your file with the following code:
87
93
@@ -94,28 +100,26 @@ headers. In this app, you'll need the `libcurl` library to make some HTTP calls.
94
100
linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lcurl
95
101
```
96
102
97
- * `headers` is the list of header files to generate Kotlin stubs. You can add multiple files to this entry,
98
- separating each with a ` \` on a new line . In this case, it' s only `curl.h`. The referenced files need to be available
99
- on the system path (in this case, it' s `/usr/include/curl`).
103
+ * `headers` is the list of header files to generate Kotlin stubs for . You can add multiple files to this entry,
104
+ separating each with a space . In this case, it' s only `curl.h`. The referenced files need to be available
105
+ on the specified path (in this case, it' s `/usr/include/curl`).
100
106
* `headerFilter` shows what exactly is included. In C, all the headers are also included when one file references
101
107
another one with the `#include` directive. Sometimes it' s not necessary, and you can add this parameter
102
- [using glob patterns](https: // en.wikipedia.org/wiki/Glob_(programming)) to fine-tune things .
108
+ [using glob patterns](https: // en.wikipedia.org/wiki/Glob_(programming)) to make adjustments .
103
109
104
- `headerFilter` is an optional argument and is mostly used when the library is installed as a system library. You don' t
105
- want to fetch external dependencies (such as system `stdint.h` header) into the interop library. It may be important to
106
- optimize the library size and fix potential conflicts between the system and the provided Kotlin/Native compilation
107
- environment.
110
+ You can use `headerFilter` if you don' t want to fetch external dependencies (such as system `stdint.h` header) into
111
+ the interop library. Also, it may be useful for library size optimization and fixing potential conflicts between the
112
+ system and the provided Kotlin/Native compilation environment.
108
113
109
- * The next lines are about providing linker and compiler options, which can vary depending on different target platforms.
110
- In this case, they are macOS (the `.osx` suffix) and Linux (the `.linux` suffix). Parameters without a suffix are also
111
- possible (for example, `linkerOpts=`) and applied to all platforms.
114
+ * If the behavior for a certain platform needs to be modified, you can use a format like `compilerOpts.osx` or `compilerOpts.linux`
115
+ to provide platform-specific values to the options. In this case, they are macOS (the `.osx` suffix) and Linux (the `.linux` suffix).
116
+ Parameters without a suffix are also possible (for example, `linkerOpts=`) and applied to all platforms.
112
117
113
- The convention is that each library gets its definition file, usually with the same name as the library. For more
114
- information on all the options available to `cinterop`, see [the Interop section](native-c-interop.md).
118
+ For the full list of available options, see [Definition file](native-definition-file.md#properties).
115
119
116
120
> You need to have the `curl` library binaries on your system to make the sample work. On macOS and Linux, they are usually
117
- > included. On Windows, you can build it from [sources](https://curl.haxx. se/download.html) (you' ll need Visual Studio or
118
- > Windows SDK Commandline tools). For more details, see the [related blog post](https: // jonnyzzz.com/blog/2018/10/29/kn-libcurl-windows/).
121
+ > included. On Windows, you can build it from [sources](https://curl.se/download.html) (you' ll need Microsoft Visual Studio or
122
+ > Windows SDK command - line tools). For more details, see the [related blog post](https: // jonnyzzz.com/blog/2018/10/29/kn-libcurl-windows/).
119
123
> Alternatively , you may want to consider a [MinGW / MSYS2 ](https: // www.msys2.org/) `curl` binary.
120
124
>
121
125
{style= " note" }
@@ -127,11 +131,11 @@ entry to the `build.gradle.kts` file:
127
131
128
132
```kotlin
129
133
nativeTarget.apply {
130
- compilations.getByName(" main" ) { // NL
131
- cinterops { // NL
132
- val libcurl by creating // NL
133
- } // NL
134
- } // NL
134
+ compilations.getByName(" main" ) {
135
+ cinterops {
136
+ val libcurl by creating
137
+ }
138
+ }
135
139
binaries {
136
140
executable {
137
141
entryPoint = " main"
@@ -140,24 +144,24 @@ nativeTarget.apply {
140
144
}
141
145
```
142
146
143
- The new lines are marked with ` // NL`. First, `cinterops` is added, and then an entry for each `def` file. By default,
144
- the name of the file is used. You can override this with additional parameters:
147
+ First , `cinterops` is added, and then an entry for a definition file. By default, the name of the file is used.
148
+ You can override this with additional parameters:
145
149
146
150
```kotlin
147
- val libcurl by creating {
148
- definitionFile.set(project.file(" src/nativeInterop/cinterop/libcurl.def" ))
149
- packageName(" com.jetbrains.handson.http" )
150
- compilerOpts(" -I/path" )
151
- includeDirs.allHeaders(" path" )
151
+ cinterops {
152
+ val libcurl by creating {
153
+ definitionFile.set(project.file(" src/nativeInterop/cinterop/libcurl.def" ))
154
+ packageName(" com.jetbrains.handson.http" )
155
+ compilerOpts(" -I/path" )
156
+ includeDirs.allHeaders(" path" )
157
+ }
152
158
}
153
159
```
154
160
155
- See the [Interoperability with C ](native- c- interop.md) section for more details on the available options.
156
-
157
161
## Write the application code
158
162
159
- Now you have the library and the corresponding Kotlin stubs and can use them from your application. For this tutorial,
160
- convert the [simple.c](https: // curl.haxx .se/libcurl/c/simple.html) example to Kotlin.
163
+ Now that you have the library and the corresponding Kotlin stubs, you can use them from your application.
164
+ For this tutorial, convert the [simple.c](https: // curl.se/libcurl/c/simple.html) example to Kotlin.
161
165
162
166
In the `src/ nativeMain/ kotlin/ ` folder, update your `Main .kt` file with the following code:
163
167
@@ -181,31 +185,37 @@ fun main(args: Array<String>) {
181
185
```
182
186
183
187
As you can see, explicit variable declarations are eliminated in the Kotlin version, but everything else is pretty much
184
- the same as the C version. All the calls you' d expect in the ` libcurl` library are available in the Kotlin equivalent.
188
+ the same as the C version. All the calls you' d expect in the libcurl library are available in the Kotlin equivalent.
185
189
186
190
> This is a line-by-line literal translation. You could also write this in a more Kotlin idiomatic way.
187
191
>
192
+ {type="tip"}
188
193
189
194
## Compile and run the application
190
195
191
- 1. Compile the application. To do that, call `runDebugExecutableNative` in the list of run Gradle tasks or use the following
196
+ 1. Compile the application. To do that, run the `runDebugExecutableNative` Gradle task from the task list or use the following
192
197
command in the terminal:
198
+
199
+ ```bash
200
+ ./gradlew runDebugExecutableNative
201
+ ```
193
202
194
- ```bash
195
- ./gradlew runDebugExecutableNative
196
- ```
197
- In this case, the `cinterop` generated part is implicitly included in the build.
203
+ In this case, the part generated by the cinterop tool is implicitly included in the build.
198
204
199
- 2. If there are no errors during compilation, click the green **Run** icon in the gutter beside the `main()` method or
200
- use the **Alt+Enter** shortcut to invoke the launch menu in IntelliJ IDEA .
205
+ 2. If there are no errors during compilation, click the green **Run** icon in the gutter next to the `main()` function or
206
+ use the < shortcut>Shift + Cmd + R</shortcut>/<shortcut>Shift + F10</shortcut> shortcut .
201
207
202
- IntelliJ IDEA opens the **Run** tab and shows the output — the contents of ` https://example.com` :
208
+ IntelliJ IDEA opens the **Run** tab and shows the output — the contents of [example.com]( https://example.com/) :
203
209
204
210
{width=700}
205
211
206
212
You can see the actual output because the call `curl_easy_perform` prints the result to the standard output. You could
207
213
hide this using `curl_easy_setopt`.
208
214
209
- > You can get the full code [here ](https://github.com/Kotlin/kotlin-hands-on-intro-kotlin-native).
215
+ > You can get the full project code in our [GitHub repository ](https://github.com/Kotlin/kotlin-hands-on-intro-kotlin-native).
210
216
>
211
217
{style="note"}
218
+
219
+ ## What' s next
220
+
221
+ Learn more about [Kotlin ' s interoperability with C](native-c-interop.md).
0 commit comments