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() {
fun toInterop(stringArray: Array<String>?): InteropPointer
fun InteropPointer.fromInteropNativePointerArray(): NativePointerArray
inline fun <reified T> InteropPointer.fromInterop(decoder: ArrayInteropDecoder<T>): Array<T>
fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer
fun release()
}
......
package org.jetbrains.skia.impl
import org.jetbrains.skia.Data
import org.jetbrains.skiko.tests.TestHelpers
import org.jetbrains.skiko.tests.runTest
import kotlin.test.Test
......@@ -46,4 +47,29 @@ class InteropScopeCommonTests {
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 {
}
}
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 {
Library.staticLoad()
}
......@@ -57,7 +70,10 @@ private external fun _nFillIntArrayOf5(interopPointer: InteropPointer)
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillDoubleArrayOf5")
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")
private external fun _nStringByIndex(index: Int): NativePointer
internal fun nativeStringByIndex(index: Int): NativePointer = _nStringByIndex(index)
\ No newline at end of file
internal fun nativeStringByIndex(index: Int): NativePointer = _nStringByIndex(index)
......@@ -190,6 +190,10 @@ actual class InteropScope actual constructor() {
return result
}
actual fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer {
return toInterop(interopPointers.toIntArray())
}
actual fun release() {
elements.forEach {
_free(it)
......
......@@ -77,6 +77,7 @@ actual open class InteropScope actual constructor() {
NativePointerArray((this as LongArray).size, this)
actual inline fun <reified T> InteropPointer.fromInterop(decoder: ArrayInteropDecoder<T>): Array<T> =
this@fromInterop as Array<T>
actual fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer = interopPointers
actual fun release() {}
}
......@@ -94,4 +95,4 @@ actual class NativePointerArray constructor(size: Int, internal val backing: Lon
actual val size: Int
get() = backing.size
}
\ No newline at end of file
}
#include <jni.h>
#include <stdlib.h>
#include "SkString.h"
......@@ -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);
}
......@@ -53,4 +53,21 @@ SKIKO_EXPORT KNativePointer org_jetbrains_skiko_tests_TestHelpers__nStringByInde
case 2: return new SkString("你好");
default: TODO("unknown");
}
}
\ No newline at end of file
}
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() {
TODO("implement native fromInteropNativePointerArray")
}
actual fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer {
return toInterop(interopPointers.map { it.toLong() }.toLongArray())
}
actual fun release() {
elements.forEach {
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