Unverified Commit 36cd5f84 authored by Oleksandr Karpovich's avatar Oleksandr Karpovich Committed by GitHub

add `toInterop()` for arrays of InteropPointer (#325)

* add `fun toInterop(interopPointers: Array<InteropPointer>): InteropPointer`

* add Test: toInteropForArrayOfInteropPointers
Co-authored-by: 's avatarOleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
parent 09aad604
...@@ -41,6 +41,7 @@ expect class InteropScope() { ...@@ -41,6 +41,7 @@ expect class InteropScope() {
fun toInterop(stringArray: Array<String>?): InteropPointer fun toInterop(stringArray: Array<String>?): InteropPointer
fun InteropPointer.fromInteropNativePointerArray(): NativePointerArray fun InteropPointer.fromInteropNativePointerArray(): NativePointerArray
inline fun <reified T> InteropPointer.fromInterop(decoder: ArrayInteropDecoder<T>): Array<T> inline fun <reified T> InteropPointer.fromInterop(decoder: ArrayInteropDecoder<T>): Array<T>
fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer
fun release() fun release()
} }
......
package org.jetbrains.skia.impl package org.jetbrains.skia.impl
import org.jetbrains.skia.Data
import org.jetbrains.skiko.tests.TestHelpers import org.jetbrains.skiko.tests.TestHelpers
import org.jetbrains.skiko.tests.runTest import org.jetbrains.skiko.tests.runTest
import kotlin.test.Test import kotlin.test.Test
...@@ -46,4 +47,29 @@ class InteropScopeCommonTests { ...@@ -46,4 +47,29 @@ class InteropScopeCommonTests {
assertContentEquals(doubleArrayOf(-0.001, 0.00222, 2.71828, 3.1415, 10000000.9991), doubleArray) assertContentEquals(doubleArrayOf(-0.001, 0.00222, 2.71828, 3.1415, 10000000.9991), doubleArray)
} }
@OptIn(ExperimentalUnsignedTypes::class)
@Test
fun toInteropForArrayOfInteropPointers() = runTest {
val arrayOfIntArrays = arrayOf(
intArrayOf(0, 1, 2, 4),
intArrayOf(100, 200, 300, 400),
intArrayOf(10000, 20000, 30000, 40000),
)
val nativePtr = TestHelpers().writeArrayOfIntArrays(arrayOfIntArrays)
val memoryOwner = object : Managed(nativePtr, NullPointer, false) {}
val data = Data.makeWithoutCopy(nativePtr, 3 * 4 * 4, memoryOwner)
val bytes = data.bytes.toUByteArray().toList()
val ints: List<Int> = bytes.chunked(4).map {
(it[3].toInt() shl 24) or (it[2].toInt() shl 16) or (it[1].toInt() shl 8) or (it[0].toInt())
}
assertContentEquals(
expected = arrayOfIntArrays.flatMap { it.toList() }.toTypedArray(),
actual = ints.toTypedArray()
)
}
} }
...@@ -37,6 +37,19 @@ class TestHelpers { ...@@ -37,6 +37,19 @@ class TestHelpers {
} }
} }
fun writeArrayOfIntArrays(array: Array<IntArray>): NativePointer {
require(array.size == 3) {
"For testing purposes, the length of the array should be 3"
}
return interopScope {
_nWriteArraysOfInts(
toInteropForArraysOfPointers(
array.map { toInterop(it) }.toTypedArray()
)
)
}
}
init { init {
Library.staticLoad() Library.staticLoad()
} }
...@@ -57,6 +70,9 @@ private external fun _nFillIntArrayOf5(interopPointer: InteropPointer) ...@@ -57,6 +70,9 @@ private external fun _nFillIntArrayOf5(interopPointer: InteropPointer)
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillDoubleArrayOf5") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillDoubleArrayOf5")
private external fun _nFillDoubleArrayOf5(interopPointer: InteropPointer) private external fun _nFillDoubleArrayOf5(interopPointer: InteropPointer)
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nWriteArraysOfInts")
private external fun _nWriteArraysOfInts(interopPointer: InteropPointer): NativePointer
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__nStringByIndex") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__nStringByIndex")
private external fun _nStringByIndex(index: Int): NativePointer private external fun _nStringByIndex(index: Int): NativePointer
......
...@@ -190,6 +190,10 @@ actual class InteropScope actual constructor() { ...@@ -190,6 +190,10 @@ actual class InteropScope actual constructor() {
return result return result
} }
actual fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer {
return toInterop(interopPointers.toIntArray())
}
actual fun release() { actual fun release() {
elements.forEach { elements.forEach {
_free(it) _free(it)
......
...@@ -77,6 +77,7 @@ actual open class InteropScope actual constructor() { ...@@ -77,6 +77,7 @@ actual open class InteropScope actual constructor() {
NativePointerArray((this as LongArray).size, this) NativePointerArray((this as LongArray).size, this)
actual inline fun <reified T> InteropPointer.fromInterop(decoder: ArrayInteropDecoder<T>): Array<T> = actual inline fun <reified T> InteropPointer.fromInterop(decoder: ArrayInteropDecoder<T>): Array<T> =
this@fromInterop as Array<T> this@fromInterop as Array<T>
actual fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer = interopPointers
actual fun release() {} actual fun release() {}
} }
......
#include <jni.h> #include <jni.h>
#include <stdlib.h>
#include "SkString.h" #include "SkString.h"
...@@ -71,3 +72,21 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_tests_TestHelpersKt_ ...@@ -71,3 +72,21 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_tests_TestHelpersKt_
} }
} }
extern "C" JNIEXPORT jlong JNICALL Java_org_jetbrains_skiko_tests_TestHelpersKt__1nWriteArraysOfInts
(JNIEnv* env, jclass jclass, jobjectArray arrayOfIntArray) {
// hardcoded length is ok for testing purposes
jsize len = 3; //(*env)->GetArrayLength(env, arrayOfIntArray);
int *mem = reinterpret_cast<int*>(malloc(3 * 4 * 4)); // 3 arrays. each array consists of 4 ints
for (int i = 0; i < len; i++) {
jintArray array = (jintArray) env->GetObjectArrayElement(arrayOfIntArray, i);
jint *result_int = env->GetIntArrayElements(array, NULL);
for (int j = 0; j < 4; j++) {
mem[(i * 4) + j] = result_int[j];
}
env->ReleaseIntArrayElements(array, result_int, 0);
}
return reinterpret_cast<jlong>(mem);
}
...@@ -54,3 +54,20 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skiko_tests_TestHelpers__nStringByInde ...@@ -54,3 +54,20 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skiko_tests_TestHelpers__nStringByInde
default: TODO("unknown"); default: TODO("unknown");
} }
} }
SKIKO_EXPORT KNativePointer org_jetbrains_skiko_tests_TestHelpers__1nWriteArraysOfInts(KNativePointer* arrayOfIntArray) {
// hardcoded length is ok for testing purposes
size_t len = 3; //(*env)->GetArrayLength(env, arrayOfIntArray);
int *mem = reinterpret_cast<int *>(malloc(3 * 4 * 4)); // 3 arrays. each array consists of 4 ints
for (int i = 0; i < len; i++) {
KNativePointer* array = reinterpret_cast<KNativePointer*>(arrayOfIntArray[i]);
int *ints = reinterpret_cast<int*>(array);
for (int j = 0; j < 4; j++) {
mem[(i * 4) + j] = ints[j];
}
}
return reinterpret_cast<KNativePointer>(mem);
}
...@@ -190,6 +190,10 @@ actual class InteropScope actual constructor() { ...@@ -190,6 +190,10 @@ actual class InteropScope actual constructor() {
TODO("implement native fromInteropNativePointerArray") TODO("implement native fromInteropNativePointerArray")
} }
actual fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer {
return toInterop(interopPointers.map { it.toLong() }.toLongArray())
}
actual fun release() { actual fun release() {
elements.forEach { elements.forEach {
it.unpin() it.unpin()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment