@@ -38,7 +38,6 @@ on macOS/iOS are available this way.
38
38
Install libgit2 and prepare stubs for the git library:
39
39
40
40
``` bash
41
-
42
41
cd samples/gitchurn
43
42
../../dist/bin/cinterop -def src/nativeInterop/cinterop/libgit2.def \
44
43
-compiler-option -I/usr/local/include -o libgit2
@@ -172,9 +171,9 @@ linkerOpts = -lpng
172
171
Target-specific options only applicable to the certain target can be specified as well:
173
172
174
173
``` 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
178
177
```
179
178
180
179
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
277
276
for accessing values by index:
278
277
279
278
``` 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 ) {
281
283
for (index in 0 .. length - 2 ) {
282
284
ptr[index] = ptr[index + 1 ]
283
285
}
@@ -296,12 +298,18 @@ Casting a pointer (including `COpaquePointer`) can be done with
296
298
` .reinterpret<T> ` , e.g.:
297
299
298
300
``` kotlin
301
+ import kotlinx.cinterop.*
302
+
303
+ @OptIn(ExperimentalForeignApi ::class )
299
304
val intPtr = bytePtr.reinterpret<IntVar >()
300
305
```
301
306
302
307
or
303
308
304
309
``` kotlin
310
+ import kotlinx.cinterop.*
311
+
312
+ @OptIn(ExperimentalForeignApi ::class )
305
313
val intPtr: CPointer <IntVar > = bytePtr.reinterpret()
306
314
```
307
315
@@ -321,15 +329,21 @@ can be omitted as usual due to the type inference.
321
329
322
330
### Memory allocation
323
331
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:
325
333
326
334
``` kotlin
335
+ import kotlinx.cinterop.*
336
+
337
+ @OptIn(ExperimentalForeignApi ::class )
327
338
val byteVar = placement.alloc<ByteVar >()
328
339
```
329
340
330
341
or
331
342
332
343
``` kotlin
344
+ import kotlinx.cinterop.*
345
+
346
+ @OptIn(ExperimentalForeignApi ::class )
333
347
val bytePtr = placement.allocArray<ByteVar >(5 )
334
348
```
335
349
@@ -338,9 +352,14 @@ It corresponds to allocating native memory with `malloc` and provides an additio
338
352
` .free() ` operation to free allocated memory:
339
353
340
354
``` 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
+ }
344
363
```
345
364
346
365
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,
349
368
so it is possible to allocate native memory with ` alloc ` and ` allocArray ` ,
350
369
and the allocated memory will be automatically freed after leaving the scope.
351
370
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:
354
372
355
373
``` kotlin
374
+ import kotlinx.cinterop.*
375
+ import platform.posix.*
376
+
377
+ @OptIn(ExperimentalForeignApi ::class )
356
378
val fileSize = memScoped {
357
379
val statBuf = alloc< stat> ()
358
380
val error = stat(" /" , statBuf.ptr)
@@ -374,24 +396,23 @@ C array literals without explicit native memory allocation.
374
396
To construct the immutable self-contained sequence of C values, the following
375
397
methods are provided:
376
398
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
380
402
381
403
For example:
382
404
383
- C:
384
-
385
405
``` c
406
+ // C:
386
407
void foo (int* elements, int count);
387
408
...
388
409
int elements[ ] = {1, 2, 3};
389
410
foo(elements, 3);
390
411
```
391
412
392
- Kotlin:
393
-
394
413
```kotlin
414
+ // Kotlin:
415
+
395
416
foo(cValuesOf(1, 2, 3), 3)
396
417
```
397
418
@@ -404,19 +425,19 @@ expecting a C string.
404
425
There are also some tools available to convert between Kotlin and C strings
405
426
manually:
406
427
407
- * ` fun CPointer<ByteVar>.toKString(): String `
408
- * ` val String.cstr: CValuesRef<ByteVar> ` .
428
+ * ` fun CPointer<ByteVar>.toKString(): String `
429
+ * ` val String.cstr: CValuesRef<ByteVar> ` .
409
430
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:
411
432
412
- ```
433
+ ``` kotlin
413
434
val cString = kotlinString.cstr.getPointer(nativeHeap)
414
435
```
415
436
416
437
In all cases, the C string is supposed to be encoded as UTF-8.
417
438
418
439
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:
420
441
421
442
``` c
422
443
noStringConversion = LoadCursorA LoadCursorW
@@ -426,6 +447,9 @@ This way any value of type `CPointer<ByteVar>` can be passed as an argument of `
426
447
If a Kotlin string should be passed, code like this could be used:
427
448
428
449
``` kotlin
450
+ import kotlinx.cinterop.*
451
+
452
+ @OptIn(kotlinx.cinterop.ExperimentalForeignApi ::class )
429
453
memScoped {
430
454
LoadCursorA (null , " cursor.bmp" .cstr.ptr) // for ASCII version
431
455
LoadCursorW (null , " cursor.bmp" .wcstr.ptr) // for Unicode version
@@ -435,15 +459,18 @@ memScoped {
435
459
### Scope-local pointers
436
460
437
461
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 { } ` .
439
463
It allows using the APIs which require C pointers with a lifetime bound to a certain ` MemScope ` . For example:
440
464
441
465
``` kotlin
466
+ import kotlinx.cinterop.*
467
+
468
+ @OptIn(kotlinx.cinterop.ExperimentalForeignApi ::class )
442
469
memScoped {
443
470
items = arrayOfNulls<CPointer <ITEM >? > (6 )
444
471
arrayOf(" one" , " two" ).forEachIndexed { index, value -> items[index] = value.cstr.ptr }
445
472
menu = new_menu(" Menu" .cstr.ptr, items.toCValues().ptr)
446
- .. .
473
+ // ...
447
474
}
448
475
```
449
476
@@ -493,6 +520,9 @@ Such wrapping is possible with `StableRef` class.
493
520
To wrap the reference:
494
521
495
522
```kotlin
523
+ import kotlinx.cinterop.*
524
+
525
+ @OptIn(ExperimentalForeignApi::class)
496
526
val stableRef = StableRef.create(kotlinReference)
497
527
val voidPtr = stableRef.asCPointer()
498
528
```
@@ -502,6 +532,7 @@ where the `voidPtr` is a `COpaquePointer` and can be passed to the C function.
502
532
To unwrap the reference:
503
533
504
534
```kotlin
535
+ @OptIn(ExperimentalForeignApi::class)
505
536
val stableRef = voidPtr.asStableRef<KotlinClass>()
506
537
val kotlinReference = stableRef.get()
507
538
```
@@ -577,6 +608,10 @@ methods, depending on `type`.
577
608
The example of using ` convert ` :
578
609
579
610
``` kotlin
611
+ import kotlinx.cinterop.*
612
+ import platform.posix.*
613
+
614
+ @OptIn(ExperimentalForeignApi ::class )
580
615
fun zeroMemory (buffer : COpaquePointer , size : Int ) {
581
616
memset(buffer, 0 , size.convert< size_t> ())
582
617
}
@@ -591,7 +626,11 @@ Kotlin objects could be pinned, i.e. their position in memory is guaranteed to b
591
626
until unpinned, and pointers to such objects inner data could be passed to the C functions. For example
592
627
593
628
``` 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 ) {
595
634
val buffer = ByteArray (1024 )
596
635
buffer.usePinned { pinned ->
597
636
while (true ) {
0 commit comments