Merge pull request #8 from JetBrains/callbacks-strike-back

Fix bugs after supporting callbacks in Interop
This commit is contained in:
SvyatoslavScherbina
2016-10-14 17:40:02 +03:00
committed by GitHub
4 changed files with 64 additions and 22 deletions
@@ -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) {
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<NativePtrBox>, 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<NativePtrBox>, 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
@@ -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<String>): NativeIndex {
// TODO: dispose all allocated memory and resources
val args1 = args.map { CString.fromString(it)!!.asCharPtr() }.toTypedArray()
val index = clang_createIndex(0, 0)
+7 -1
View File
@@ -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);
@@ -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<Type>) =
"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<NativePtrBox>, ret: NativePtr) {")
indent {