Refresh interop docs. (#2130)

This commit is contained in:
Nikolay Igotti
2018-09-25 15:55:45 +03:00
committed by GitHub
parent 5acd49215b
commit 9b2a03b6cd
2 changed files with 91 additions and 38 deletions
+4 -3
View File
@@ -1,8 +1,9 @@
### Q: How do I run my program? ### Q: How do I run my program?
A: Define a top level function `fun main(args: Array<String>)`, please ensure it's not A: Define a top level function `fun main(args: Array<String>)` or just `fun main()` if you are not interested
in a package. Also compiler switch `-entry` could be used to make any function taking in passed arguments, please ensure it's not in a package.
`Array<String>` and return `Unit` as an entry point. Also compiler switch `-entry` could be used to make any function taking `Array<String>` or no arguments
and return `Unit` as an entry point.
### Q: What is Kotlin/Native memory management model? ### Q: What is Kotlin/Native memory management model?
+87 -35
View File
@@ -20,60 +20,49 @@ imported into an IDE for the purpose of code completion and navigation.
Interoperability with Swift/Objective-C is provided too and covered in a Interoperability with Swift/Objective-C is provided too and covered in a
separate document [OBJC_INTEROP.md](OBJC_INTEROP.md). separate document [OBJC_INTEROP.md](OBJC_INTEROP.md).
## Platform libraries ##
Note that in many cases there's no need to use custom interoperability library creation mechanisms described below,
as for APIs available on the platform standartized bindings called [platform libraries](PLATFORM_LIBS.md)
could be used. For example, POSIX on Linux/macOS platforms, Win32 on Windows platform, or Apple frameworks
on macOS/iOS are available this way.
## Simple example ## ## Simple example ##
Build the dependencies and compiler (see `README.md`). Install libgit2 and prepare stubs for the git library:
Prepare stubs for the system sockets library:
<div class="sample" markdown="1" theme="idea" mode="shell"> <div class="sample" markdown="1" theme="idea" mode="shell">
```bash ```bash
cd samples/socket cd samples/gitchurn
../../dist/bin/cinterop -def src/main/c_interop/sockets.def \ ../../dist/bin/cinterop -def src/main/c_interop/libgit2.def \
-o sockets -compilerOpts -I/usr/local/include -o libgit2
``` ```
</div> </div>
Compile the echo server: Compile the client:
<div class="sample" markdown="1" theme="idea" mode="shell"> <div class="sample" markdown="1" theme="idea" mode="shell">
```bash ```bash
../../dist/bin/kotlinc src/main/kotlin/EchoServer.kt \ ../../dist/bin/kotlinc src/main/kotlin \
-library sockets -o EchoServer -library libgit2 -o GitChurn
``` ```
</div> </div>
Run the client:
This whole process is automated in the `build.sh` script, which also supports cross-compilation
to supported cross-targets with `TARGET=raspberrypi ./build.sh` (the `cross_dist` target must
be executed first).
Run the server:
<div class="sample" markdown="1" theme="idea" mode="shell"> <div class="sample" markdown="1" theme="idea" mode="shell">
```bash ```bash
./EchoServer.kexe 3000 & ./GitChurn.kexe ../..
``` ```
</div> </div>
Test the server by connecting to it, for example with telnet:
<div class="sample" markdown="1" theme="idea" mode="shell">
```bash
telnet localhost 3000
```
</div>
Write something to the console and watch the server echo it back.
## Creating bindings for a new library ## ## Creating bindings for a new library ##
@@ -83,8 +72,9 @@ Structurally it's a simple property file, which looks like this:
<div class="sample" markdown="1" theme="idea" mode="c"> <div class="sample" markdown="1" theme="idea" mode="c">
```c ```c
headers = zlib.h headers = png.h
compilerOpts = -std=c99 headerFilter = png.h
package = png
``` ```
</div> </div>
@@ -96,14 +86,14 @@ in the sysroot search paths, headers may be needed):
<div class="sample" markdown="1" theme="idea" mode="shell"> <div class="sample" markdown="1" theme="idea" mode="shell">
```bash ```bash
cinterop -def zlib.def -copt -I/opt/local/include -o zlib cinterop -def png.def -compilerOpts -I/usr/local/include -o png
``` ```
</div> </div>
This command will produce a `zlib.klib` compiled library and This command will produce a `png.klib` compiled library and
`zlib-build/kotlin` directory containing Kotlin source code for the library. `png-build/kotlin` directory containing Kotlin source code for the library.
If the behavior for a certain platform needs to be modified, you can use a format like If the behavior for a certain platform needs to be modified, you can use a format like
`compilerOpts.osx` or `compilerOpts.linux` to provide platform-specific values `compilerOpts.osx` or `compilerOpts.linux` to provide platform-specific values
@@ -178,9 +168,39 @@ excludeDependentModules = true
When both `excludeDependentModules` and `headerFilter` are used, they are When both `excludeDependentModules` and `headerFilter` are used, they are
applied as an intersection. applied as an intersection.
### C compiler and linker options ###
Options passed to the C compiler (used to analyze headers, such as preprocessor definitions) and the linker
(used to link final executables) can be passed in the definition file as `compilerOpts` and `linkerOpts`
respectively. For example
<div class="sample" markdown="1" theme="idea" mode="c">
```c
compilerOpts = -DFOO=bar
linkerOpts = -lpng
```
</div>
Target-specific options, only applicable to the certain target can be specified as well, such as
<div class="sample" markdown="1" theme="idea" mode="c">
```c
compilerOpts = -DBAR=bar
compilerOpts.linux_x64 = -DFOO=foo1
compilerOpts.mac_x64 = -DFOO=foo2
```
</div>
and so, C headers on Linux will be analyzed with `-DBAR=bar -DFOO=foo1` and on macOS with `-DBAR=bar -DFOO=foo2`.
Note that any definition file option can have both common and the platform-specific part.
### Adding custom declarations ### ### Adding custom declarations ###
Sometimes it is required to add custom C declarations to the library before Sometimes it is required to add custom C declarations to the library before
generating bindings (e.g., for [macros](#macros)). Instead of creating an generating bindings (e.g., for [macros](#macros)). Instead of creating an
additional header file with these declarations, you can include them directly additional header file with these declarations, you can include them directly
to the end of the `.def` file, after a separating line, containing only the to the end of the `.def` file, after a separating line, containing only the
@@ -351,7 +371,7 @@ or
<div class="sample" markdown="1" theme="idea" data-highlight-only> <div class="sample" markdown="1" theme="idea" data-highlight-only>
```kotlin ```kotlin
val bytePtr = placement.allocArray<ByteVar>(5): val bytePtr = placement.allocArray<ByteVar>(5)
``` ```
</div> </div>
@@ -635,9 +655,12 @@ The `.def` file supports several options for adjusting the generated bindings.
values correspondingly. If the enum is not included into any of these lists, values correspondingly. If the enum is not included into any of these lists,
then it is generated according to the heuristics. then it is generated according to the heuristics.
* `noStringConversion` property value is space-separated lists of the functions whose
`const char*` parameters shall not be autoconverted as Kotlin string
### Portability ### ### Portability ###
Sometimes the C libraries have function parameters or struct fields of a Sometimes the C libraries have function parameters or struct fields of a
platform-dependent type, e.g. `long` or `size_t`. Kotlin itself doesn't provide platform-dependent type, e.g. `long` or `size_t`. Kotlin itself doesn't provide
neither implicit integer casts nor C-style integer casts (e.g. neither implicit integer casts nor C-style integer casts (e.g.
`(size_t) intValue`), so to make writing portable code in such cases easier, `(size_t) intValue`), so to make writing portable code in such cases easier,
@@ -671,3 +694,32 @@ fun zeroMemory(buffer: COpaquePointer, size: Int) {
Also, the type parameter can be inferred automatically and so may be omitted Also, the type parameter can be inferred automatically and so may be omitted
in some cases. in some cases.
### Object pinning ###
Kotlin objects could be pinned, i.e. their position in memory is guaranteed to be stable
until unpinned, and pointers to such objects inner data could be passed to the C functions. For example
<div class="sample" markdown="1" theme="idea" data-highlight-only>
```kotlin
fun readData(fd: Int): String {
val buffer = ByteArray(1024)
buffer.usePinned { pinned ->
while (true) {
val length = recv(fd, pinned.addressOf(0), buffer.size.convert(), 0).toInt()
if (length <= 0) {
break
}
// Now `buffer` has raw data obtained from the `recv()` call.
}
}
}
```
</div>
Here we use service function `usePinned`, which pins an object, executes block and unpins it on normal and
exception paths.