Merge pull request #8 from JetBrains/callbacks-strike-back
Fix bugs after supporting callbacks in Interop
This commit is contained in:
@@ -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<NativePtrBox>, ret: NativePtr) {
|
override fun invoke(function: (CXCursor, CXCursor, NativePtr?) -> CXChildVisitResult, args: NativeArray<NativePtrBox>, ret: NativePtr) {
|
||||||
val res = function(args[0].value.asRef(CXCursor)!!, args[1].value.asRef(CXCursor)!!, args[2].value.asRef(NativePtrBox)!!.value)
|
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
|
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<NativePtrBox>, ret: NativePtr) {
|
override fun invoke(function: (CXCursor, NativePtr?) -> CXVisitorResult, args: NativeArray<NativePtrBox>, ret: NativePtr) {
|
||||||
val res = function(args[0].value.asRef(CXCursor)!!, args[1].value.asRef(NativePtrBox)!!.value)
|
val res = function(args[0].value.asRef(CXCursor)!!, args[1].value.asRef(NativePtrBox)!!.value)
|
||||||
CXVisitorResult.ref.byPtr(ret).value = res
|
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<NativePtrBox>, ret: NativePtr) {
|
override fun invoke(function: (NativePtr?, CXCursor, CXSourceRange) -> CXVisitorResult, args: NativeArray<NativePtrBox>, ret: NativePtr) {
|
||||||
val res = function(args[0].value.asRef(NativePtrBox)!!.value, args[1].value.asRef(CXCursor)!!, args[2].value.asRef(CXSourceRange)!!)
|
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
|
CXVisitorResult.ref.byPtr(ret).value = res
|
||||||
|
|||||||
+21
-9
@@ -98,16 +98,27 @@ private class NativeIndexImpl : NativeIndex() {
|
|||||||
* Computes [StructDef.hasNaturalLayout] property.
|
* Computes [StructDef.hasNaturalLayout] property.
|
||||||
*/
|
*/
|
||||||
fun structHasNaturalLayout(structDefCursor: CXCursor): Boolean {
|
fun structHasNaturalLayout(structDefCursor: CXCursor): Boolean {
|
||||||
val hasAttributes = malloc(Int32Box)
|
val defKind = structDefCursor.kind.value
|
||||||
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
|
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 {
|
fun convertType(type: CXType): Type {
|
||||||
@@ -253,6 +264,7 @@ fun CXString.convertAndDispose(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun buildNativeIndexImpl(headerFile: File, args: List<String>): NativeIndex {
|
fun buildNativeIndexImpl(headerFile: File, args: List<String>): NativeIndex {
|
||||||
|
// TODO: dispose all allocated memory and resources
|
||||||
val args1 = args.map { CString.fromString(it)!!.asCharPtr() }.toTypedArray()
|
val args1 = args.map { CString.fromString(it)!!.asCharPtr() }.toTypedArray()
|
||||||
|
|
||||||
val index = clang_createIndex(0, 0)
|
val index = clang_createIndex(0, 0)
|
||||||
|
|||||||
@@ -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) {
|
JNIEXPORT jlong JNICALL Java_kotlin_1native_interop_CallbacksKt_ffiTypeStruct0(JNIEnv *env, jclass cls, jlong elements) {
|
||||||
ffi_type* res = malloc(sizeof(ffi_type));
|
ffi_type* res = malloc(sizeof(ffi_type));
|
||||||
if (res != NULL) {
|
if (res != NULL) {
|
||||||
|
res->size = 0;
|
||||||
|
res->alignment = 0;
|
||||||
res->elements = (ffi_type**) elements;
|
res->elements = (ffi_type**) elements;
|
||||||
res->type = FFI_TYPE_STRUCT;
|
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 jmethodID ffiFunImpl0 = NULL;
|
||||||
static jclass cls = NULL;
|
static jclass cls = NULL;
|
||||||
if (ffiFunImpl0 == 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);
|
checkException(env);
|
||||||
assert(cls != NULL);
|
assert(cls != NULL);
|
||||||
|
|
||||||
|
|||||||
+33
-9
@@ -374,7 +374,7 @@ class StubGenerator(
|
|||||||
|
|
||||||
is RecordType -> {
|
is RecordType -> {
|
||||||
val refType = getKotlinTypeForRefTo(type)
|
val refType = getKotlinTypeForRefTo(type)
|
||||||
InValueBinding(
|
return InValueBinding(
|
||||||
kotlinJniBridgeType = "Long",
|
kotlinJniBridgeType = "Long",
|
||||||
conv = { "NativePtr.byValue($it).asRef(${refType.typeExpr})!!" },
|
conv = { "NativePtr.byValue($it).asRef(${refType.typeExpr})!!" },
|
||||||
kotlinType = refType.typeName
|
kotlinType = refType.typeName
|
||||||
@@ -386,6 +386,16 @@ class StubGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getCallbackParamBinding(type: Type): InValueBinding {
|
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)
|
return getInValueBinding(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,6 +588,11 @@ class StubGenerator(
|
|||||||
out("}")
|
out("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getFfiStructType(elementTypes: List<Type>) =
|
||||||
|
"Struct(" +
|
||||||
|
elementTypes.map { getFfiType(it) }.joinToString(", ") +
|
||||||
|
")"
|
||||||
|
|
||||||
private fun getFfiType(type: Type): String {
|
private fun getFfiType(type: Type): String {
|
||||||
return when(type) {
|
return when(type) {
|
||||||
is VoidType -> "Void"
|
is VoidType -> "Void"
|
||||||
@@ -588,29 +603,38 @@ class StubGenerator(
|
|||||||
is Int32Type -> "SInt32"
|
is Int32Type -> "SInt32"
|
||||||
is UInt32Type -> "UInt32"
|
is UInt32Type -> "UInt32"
|
||||||
is IntPtrType, is UIntPtrType, // TODO
|
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 EnumType -> getFfiType(type.def.baseType)
|
||||||
is RecordType -> {
|
is RecordType -> {
|
||||||
val def = type.decl.def!!
|
val def = type.decl.def!!
|
||||||
if (!def.hasNaturalLayout) {
|
if (!def.hasNaturalLayout) {
|
||||||
throw NotImplementedError() // TODO: represent pointer to function as NativePtr instead
|
throw NotImplementedError() // TODO: represent pointer to function as NativePtr instead
|
||||||
}
|
}
|
||||||
"Struct(" + def.fields.map {
|
getFfiStructType(def.fields.map { it.type })
|
||||||
getFfiType(it.type)
|
|
||||||
}.joinToString(", ") + ")"
|
|
||||||
}
|
}
|
||||||
else -> throw NotImplementedError(type.toString())
|
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) {
|
private fun generateFunctionType(type: FunctionType, name: String) {
|
||||||
val kotlinFunctionType = getKotlinFunctionType(type)
|
val kotlinFunctionType = getKotlinFunctionType(type)
|
||||||
|
|
||||||
val constructorArgs = listOf(type.returnType, *type.parameterTypes.toTypedArray()).map {
|
val constructorArgs = listOf(getRetValFfiType(type.returnType)) +
|
||||||
getFfiType(it)
|
type.parameterTypes.map { getArgFfiType(it) }
|
||||||
}.joinToString(", ")
|
|
||||||
|
|
||||||
out("object $name : NativeFunctionType<$kotlinFunctionType>($constructorArgs) {")
|
val constructorArgsStr = constructorArgs.joinToString(", ")
|
||||||
|
|
||||||
|
out("object $name : NativeFunctionType<$kotlinFunctionType>($constructorArgsStr) {")
|
||||||
indent {
|
indent {
|
||||||
out("override fun invoke(function: $kotlinFunctionType, args: NativeArray<NativePtrBox>, ret: NativePtr) {")
|
out("override fun invoke(function: $kotlinFunctionType, args: NativeArray<NativePtrBox>, ret: NativePtr) {")
|
||||||
indent {
|
indent {
|
||||||
|
|||||||
Reference in New Issue
Block a user