Skip to content

Commit ffb7202

Browse files
authored
fix: missing imports and annotations (#4260)
1 parent d5eeaf3 commit ffb7202

File tree

1 file changed

+65
-26
lines changed

1 file changed

+65
-26
lines changed

docs/topics/native/native-c-interop.md

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ on macOS/iOS are available this way.
3838
Install libgit2 and prepare stubs for the git library:
3939

4040
```bash
41-
4241
cd samples/gitchurn
4342
../../dist/bin/cinterop -def src/nativeInterop/cinterop/libgit2.def \
4443
-compiler-option -I/usr/local/include -o libgit2
@@ -172,9 +171,9 @@ linkerOpts = -lpng
172171
Target-specific options only applicable to the certain target can be specified as well:
173172

174173
```c
175-
compilerOpts = -DBAR=bar
176-
compilerOpts.linux_x64 = -DFOO=foo1
177-
compilerOpts.macos_x64 = -DFOO=foo2
174+
compilerOpts = -DBAR=bar
175+
compilerOpts.linux_x64 = -DFOO=foo1
176+
compilerOpts.macos_x64 = -DFOO=foo2
178177
```
179178

180179
With such a configuration, C headers will be analyzed with `-DBAR=bar -DFOO=foo1` on Linux and
@@ -277,7 +276,10 @@ Since the arrays are also mapped to `CPointer<T>`, it supports the `[]` operator
277276
for accessing values by index:
278277

279278
```kotlin
280-
fun shift(ptr: CPointer<BytePtr>, length: Int) {
279+
import kotlinx.cinterop.*
280+
281+
@OptIn(ExperimentalForeignApi::class)
282+
fun shift(ptr: CPointer<ByteVar>, length: Int) {
281283
for (index in 0 .. length - 2) {
282284
ptr[index] = ptr[index + 1]
283285
}
@@ -296,12 +298,18 @@ Casting a pointer (including `COpaquePointer`) can be done with
296298
`.reinterpret<T>`, e.g.:
297299

298300
```kotlin
301+
import kotlinx.cinterop.*
302+
303+
@OptIn(ExperimentalForeignApi::class)
299304
val intPtr = bytePtr.reinterpret<IntVar>()
300305
```
301306

302307
or
303308

304309
```kotlin
310+
import kotlinx.cinterop.*
311+
312+
@OptIn(ExperimentalForeignApi::class)
305313
val intPtr: CPointer<IntVar> = bytePtr.reinterpret()
306314
```
307315

@@ -321,15 +329,21 @@ can be omitted as usual due to the type inference.
321329

322330
### Memory allocation
323331

324-
The native memory can be allocated using the `NativePlacement` interface, e.g.
332+
The native memory can be allocated using the `NativePlacement` interface, for example:
325333

326334
```kotlin
335+
import kotlinx.cinterop.*
336+
337+
@OptIn(ExperimentalForeignApi::class)
327338
val byteVar = placement.alloc<ByteVar>()
328339
```
329340

330341
or
331342

332343
```kotlin
344+
import kotlinx.cinterop.*
345+
346+
@OptIn(ExperimentalForeignApi::class)
333347
val bytePtr = placement.allocArray<ByteVar>(5)
334348
```
335349

@@ -338,9 +352,14 @@ It corresponds to allocating native memory with `malloc` and provides an additio
338352
`.free()` operation to free allocated memory:
339353

340354
```kotlin
341-
val buffer = nativeHeap.allocArray<ByteVar>(size)
342-
<use buffer>
343-
nativeHeap.free(buffer)
355+
import kotlinx.cinterop.*
356+
357+
@OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
358+
fun main() {
359+
val size: Long = 0
360+
val buffer = nativeHeap.allocArray<ByteVar>(size)
361+
nativeHeap.free(buffer)
362+
}
344363
```
345364

346365
However, the lifetime of allocated memory is often bound to the lexical scope.
@@ -349,10 +368,13 @@ Inside the braces, the temporary placement is available as an implicit receiver,
349368
so it is possible to allocate native memory with `alloc` and `allocArray`,
350369
and the allocated memory will be automatically freed after leaving the scope.
351370

352-
For example, the C function returning values through pointer parameters can be
353-
used like
371+
For example, the C function returning values through pointer parameters can be used like:
354372

355373
```kotlin
374+
import kotlinx.cinterop.*
375+
import platform.posix.*
376+
377+
@OptIn(ExperimentalForeignApi::class)
356378
val fileSize = memScoped {
357379
val statBuf = alloc<stat>()
358380
val error = stat("/", statBuf.ptr)
@@ -374,24 +396,23 @@ C array literals without explicit native memory allocation.
374396
To construct the immutable self-contained sequence of C values, the following
375397
methods are provided:
376398

377-
* `${type}Array.toCValues()`, where `type` is the Kotlin primitive type
378-
* `Array<CPointer<T>?>.toCValues()`, `List<CPointer<T>?>.toCValues()`
379-
* `cValuesOf(vararg elements: ${type})`, where `type` is a primitive or pointer
399+
* `${type}Array.toCValues()`, where `type` is the Kotlin primitive type
400+
* `Array<CPointer<T>?>.toCValues()`, `List<CPointer<T>?>.toCValues()`
401+
* `cValuesOf(vararg elements: ${type})`, where `type` is a primitive or pointer
380402

381403
For example:
382404

383-
C:
384-
385405
```c
406+
// C:
386407
void foo(int* elements, int count);
387408
...
388409
int elements[] = {1, 2, 3};
389410
foo(elements, 3);
390411
```
391412
392-
Kotlin:
393-
394413
```kotlin
414+
// Kotlin:
415+
395416
foo(cValuesOf(1, 2, 3), 3)
396417
```
397418

@@ -404,19 +425,19 @@ expecting a C string.
404425
There are also some tools available to convert between Kotlin and C strings
405426
manually:
406427

407-
* `fun CPointer<ByteVar>.toKString(): String`
408-
* `val String.cstr: CValuesRef<ByteVar>`.
428+
* `fun CPointer<ByteVar>.toKString(): String`
429+
* `val String.cstr: CValuesRef<ByteVar>`.
409430

410-
To get the pointer, `.cstr` should be allocated in native memory, e.g.
431+
To get the pointer, `.cstr` should be allocated in native memory, for example:
411432

412-
```
433+
```kotlin
413434
val cString = kotlinString.cstr.getPointer(nativeHeap)
414435
```
415436

416437
In all cases, the C string is supposed to be encoded as UTF-8.
417438

418439
To skip automatic conversion and ensure raw pointers are used in the bindings, a `noStringConversion`
419-
statement in the `.def` file could be used, i.e.
440+
statement in the `.def` file could be used:
420441

421442
```c
422443
noStringConversion = LoadCursorA LoadCursorW
@@ -426,6 +447,9 @@ This way any value of type `CPointer<ByteVar>` can be passed as an argument of `
426447
If a Kotlin string should be passed, code like this could be used:
427448

428449
```kotlin
450+
import kotlinx.cinterop.*
451+
452+
@OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
429453
memScoped {
430454
LoadCursorA(null, "cursor.bmp".cstr.ptr) // for ASCII version
431455
LoadCursorW(null, "cursor.bmp".wcstr.ptr) // for Unicode version
@@ -435,15 +459,18 @@ memScoped {
435459
### Scope-local pointers
436460

437461
It is possible to create a scope-stable pointer of C representation of `CValues<T>`
438-
instance using the `CValues<T>.ptr` extension property, available under `memScoped { ... }`.
462+
instance using the `CValues<T>.ptr` extension property, available under `memScoped { }`.
439463
It allows using the APIs which require C pointers with a lifetime bound to a certain `MemScope`. For example:
440464

441465
```kotlin
466+
import kotlinx.cinterop.*
467+
468+
@OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
442469
memScoped {
443470
items = arrayOfNulls<CPointer<ITEM>?>(6)
444471
arrayOf("one", "two").forEachIndexed { index, value -> items[index] = value.cstr.ptr }
445472
menu = new_menu("Menu".cstr.ptr, items.toCValues().ptr)
446-
...
473+
// ...
447474
}
448475
```
449476

@@ -493,6 +520,9 @@ Such wrapping is possible with `StableRef` class.
493520
To wrap the reference:
494521
495522
```kotlin
523+
import kotlinx.cinterop.*
524+
525+
@OptIn(ExperimentalForeignApi::class)
496526
val stableRef = StableRef.create(kotlinReference)
497527
val voidPtr = stableRef.asCPointer()
498528
```
@@ -502,6 +532,7 @@ where the `voidPtr` is a `COpaquePointer` and can be passed to the C function.
502532
To unwrap the reference:
503533
504534
```kotlin
535+
@OptIn(ExperimentalForeignApi::class)
505536
val stableRef = voidPtr.asStableRef<KotlinClass>()
506537
val kotlinReference = stableRef.get()
507538
```
@@ -577,6 +608,10 @@ methods, depending on `type`.
577608
The example of using `convert`:
578609

579610
```kotlin
611+
import kotlinx.cinterop.*
612+
import platform.posix.*
613+
614+
@OptIn(ExperimentalForeignApi::class)
580615
fun zeroMemory(buffer: COpaquePointer, size: Int) {
581616
memset(buffer, 0, size.convert<size_t>())
582617
}
@@ -591,7 +626,11 @@ Kotlin objects could be pinned, i.e. their position in memory is guaranteed to b
591626
until unpinned, and pointers to such objects inner data could be passed to the C functions. For example
592627

593628
```kotlin
594-
fun readData(fd: Int): String {
629+
import kotlinx.cinterop.*
630+
import platform.posix.*
631+
632+
@OptIn(ExperimentalForeignApi::class)
633+
fun readData(fd: Int) {
595634
val buffer = ByteArray(1024)
596635
buffer.usePinned { pinned ->
597636
while (true) {

0 commit comments

Comments
 (0)