diff --git a/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/Clang.kt b/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/Clang.kt index 49cde2d3db9..03d658f40de 100644 --- a/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/Clang.kt +++ b/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/Clang.kt @@ -3570,7 +3570,7 @@ enum class CXIndexOptFlags(val value: Int) { } } -object NativeFunctionType1 : NativeFunctionType<(CXCursor, CXCursor, NativePtr?) -> CXChildVisitResult>(UInt32, Struct(UInt32, SInt32, Pointer), Struct(UInt32, SInt32, Pointer), Pointer) { +object NativeFunctionType1 : NativeFunctionType<(CXCursor, CXCursor, NativePtr?) -> CXChildVisitResult>(UInt32, Struct(UInt32, SInt32, Struct(Pointer, Pointer, Pointer)), Struct(UInt32, SInt32, Struct(Pointer, Pointer, Pointer)), Pointer) { override fun invoke(function: (CXCursor, CXCursor, NativePtr?) -> CXChildVisitResult, args: NativeArray, ret: NativePtr) { val res = function(args[0].value.asRef(CXCursor)!!, args[1].value.asRef(CXCursor)!!, args[2].value.asRef(NativePtrBox)!!.value) CXChildVisitResult.ref.byPtr(ret).value = res @@ -3589,14 +3589,14 @@ object NativeFunctionType3 : NativeFunctionType<(NativePtr?, CXSourceLocation?, } } -object NativeFunctionType4 : NativeFunctionType<(CXCursor, NativePtr?) -> CXVisitorResult>(UInt32, Struct(UInt32, SInt32, Pointer), Pointer) { +object NativeFunctionType4 : NativeFunctionType<(CXCursor, NativePtr?) -> CXVisitorResult>(UInt32, Struct(UInt32, SInt32, Struct(Pointer, Pointer, Pointer)), Pointer) { override fun invoke(function: (CXCursor, NativePtr?) -> CXVisitorResult, args: NativeArray, ret: NativePtr) { val res = function(args[0].value.asRef(CXCursor)!!, args[1].value.asRef(NativePtrBox)!!.value) CXVisitorResult.ref.byPtr(ret).value = res } } -object NativeFunctionType5 : NativeFunctionType<(NativePtr?, CXCursor, CXSourceRange) -> CXVisitorResult>(UInt32, Pointer, Struct(UInt32, SInt32, Pointer), Struct(Pointer, UInt32, UInt32)) { +object NativeFunctionType5 : NativeFunctionType<(NativePtr?, CXCursor, CXSourceRange) -> CXVisitorResult>(UInt32, Pointer, Struct(UInt32, SInt32, Struct(Pointer, Pointer, Pointer)), Struct(Struct(Pointer, Pointer), UInt32, UInt32)) { override fun invoke(function: (NativePtr?, CXCursor, CXSourceRange) -> CXVisitorResult, args: NativeArray, ret: NativePtr) { val res = function(args[0].value.asRef(NativePtrBox)!!.value, args[1].value.asRef(CXCursor)!!, args[2].value.asRef(CXSourceRange)!!) CXVisitorResult.ref.byPtr(ret).value = res diff --git a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt index ab0ac552182..86dcdb37ad4 100644 --- a/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt +++ b/Interop/Indexer/src/main/kotlin/org/jetbrains/kotlin/native/interop/indexer/Indexer.kt @@ -98,16 +98,27 @@ private class NativeIndexImpl : NativeIndex() { * Computes [StructDef.hasNaturalLayout] property. */ fun structHasNaturalLayout(structDefCursor: CXCursor): Boolean { - val hasAttributes = malloc(Int32Box) - hasAttributes.value = 0 - clang_visitChildren(structDefCursor, { cursor, parent, clientData -> - if (clang_isAttribute(cursor.kind.value) != 0) { - clientData.asRef(Int32Box)!!.value = 1 - } - CXChildVisitResult.CXChildVisit_Continue - }, hasAttributes.ptr) + val defKind = structDefCursor.kind.value - return hasAttributes.value == 0 + when (defKind) { + + CXCursorKind.CXCursor_UnionDecl -> return false + + CXCursorKind.CXCursor_StructDecl -> { + val hasAttributes = arena.alloc(Int32Box) + hasAttributes.value = 0 + clang_visitChildren(structDefCursor, { cursor, parent, clientData -> + if (clang_isAttribute(cursor.kind.value) != 0) { + clientData.asRef(Int32Box)!!.value = 1 + } + CXChildVisitResult.CXChildVisit_Continue + }, hasAttributes.ptr) + + return hasAttributes.value == 0 + } + + else -> throw IllegalArgumentException(defKind.toString()) + } } fun convertType(type: CXType): Type { @@ -253,6 +264,7 @@ fun CXString.convertAndDispose(): String { } fun buildNativeIndexImpl(headerFile: File, args: List): NativeIndex { + // TODO: dispose all allocated memory and resources val args1 = args.map { CString.fromString(it)!!.asCharPtr() }.toTypedArray() val index = clang_createIndex(0, 0) diff --git a/Interop/Runtime/src/callbacks/c/callbacks.c b/Interop/Runtime/src/callbacks/c/callbacks.c index d4a5b30b9f7..44f90608f65 100644 --- a/Interop/Runtime/src/callbacks/c/callbacks.c +++ b/Interop/Runtime/src/callbacks/c/callbacks.c @@ -101,6 +101,8 @@ JNIEXPORT jlong JNICALL Java_kotlin_1native_interop_CallbacksKt_ffiTypePointer(J JNIEXPORT jlong JNICALL Java_kotlin_1native_interop_CallbacksKt_ffiTypeStruct0(JNIEnv *env, jclass cls, jlong elements) { ffi_type* res = malloc(sizeof(ffi_type)); if (res != NULL) { + res->size = 0; + res->alignment = 0; res->elements = (ffi_type**) elements; res->type = FFI_TYPE_STRUCT; } @@ -164,7 +166,11 @@ static void ffi_fun(ffi_cif *cif, void *ret, void **args, void *user_data) { static jmethodID ffiFunImpl0 = NULL; static jclass cls = NULL; if (ffiFunImpl0 == NULL) { - cls = (*env)->FindClass(env, "kotlin_native/interop/CallbacksKt"); + jclass clsLocal = (*env)->FindClass(env, "kotlin_native/interop/CallbacksKt"); + checkException(env); + assert(clsLocal != NULL); + + cls = (jclass) (*env)->NewGlobalRef(env, clsLocal); checkException(env); assert(cls != NULL); diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt index 72bce02dbfb..3939343b015 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt @@ -374,7 +374,7 @@ class StubGenerator( is RecordType -> { val refType = getKotlinTypeForRefTo(type) - InValueBinding( + return InValueBinding( kotlinJniBridgeType = "Long", conv = { "NativePtr.byValue($it).asRef(${refType.typeExpr})!!" }, kotlinType = refType.typeName @@ -386,6 +386,16 @@ class StubGenerator( } fun getCallbackParamBinding(type: Type): InValueBinding { + when (type) { + is RecordType -> { + val refType = getKotlinTypeForRefTo(type) + return InValueBinding( + kotlinJniBridgeType = "Long", + conv = { throw UnsupportedOperationException() }, + kotlinType = refType.typeName + ) + } + } return getInValueBinding(type) } @@ -578,6 +588,11 @@ class StubGenerator( out("}") } + private fun getFfiStructType(elementTypes: List) = + "Struct(" + + elementTypes.map { getFfiType(it) }.joinToString(", ") + + ")" + private fun getFfiType(type: Type): String { return when(type) { is VoidType -> "Void" @@ -588,29 +603,38 @@ class StubGenerator( is Int32Type -> "SInt32" is UInt32Type -> "UInt32" is IntPtrType, is UIntPtrType, // TODO - is PointerType, is ArrayType -> "Pointer" + is PointerType -> "Pointer" + is ConstArrayType -> getFfiStructType( + Array(type.length.toInt(), { type.elemType }).toList() + ) is EnumType -> getFfiType(type.def.baseType) is RecordType -> { val def = type.decl.def!! if (!def.hasNaturalLayout) { throw NotImplementedError() // TODO: represent pointer to function as NativePtr instead } - "Struct(" + def.fields.map { - getFfiType(it.type) - }.joinToString(", ") + ")" + getFfiStructType(def.fields.map { it.type }) } else -> throw NotImplementedError(type.toString()) } } + private fun getArgFfiType(type: Type) = when (type) { + is ArrayType -> "Pointer" + else -> getFfiType(type) + } + + private fun getRetValFfiType(type: Type) = getArgFfiType(type) + private fun generateFunctionType(type: FunctionType, name: String) { val kotlinFunctionType = getKotlinFunctionType(type) - val constructorArgs = listOf(type.returnType, *type.parameterTypes.toTypedArray()).map { - getFfiType(it) - }.joinToString(", ") + val constructorArgs = listOf(getRetValFfiType(type.returnType)) + + type.parameterTypes.map { getArgFfiType(it) } - out("object $name : NativeFunctionType<$kotlinFunctionType>($constructorArgs) {") + val constructorArgsStr = constructorArgs.joinToString(", ") + + out("object $name : NativeFunctionType<$kotlinFunctionType>($constructorArgsStr) {") indent { out("override fun invoke(function: $kotlinFunctionType, args: NativeArray, ret: NativePtr) {") indent {