Improve function types support in interop

* Support `typedef` to function type without pointer;
* Support 64-bit integers in function types;
* Generate opaque function type on JVM if not supported.

Fix other minor bugs.
This commit is contained in:
Svyatoslav Scherbina
2017-03-15 14:17:01 +07:00
committed by SvyatoslavScherbina
parent 397928b066
commit d1859dd280
2 changed files with 18 additions and 10 deletions
@@ -281,10 +281,12 @@ class CFunction<T : CFunctionType>(override val rawPtr: NativePtr) : CPointed
/** /**
* The pointer to [CFunction]. * The pointer to [CFunction].
* TODO: remove.
*/ */
typealias CFunctionPointer<T> = CPointer<CFunction<T>> typealias CFunctionPointer<T> = CPointer<CFunction<T>>
/** /**
* The variable containing a [CFunctionPointer]. * The variable containing a [CFunctionPointer].
* TODO: remove.
*/ */
typealias CFunctionPointerVar<T> = CPointerVarWithValueMappedTo<CFunctionPointer<T>> typealias CFunctionPointerVar<T> = CPointerVarWithValueMappedTo<CFunctionPointer<T>>
@@ -189,8 +189,7 @@ class StubGenerator(
is PointerType -> { is PointerType -> {
val pointeeType = this.pointeeType val pointeeType = this.pointeeType
if (pointeeType is FunctionType) { if (pointeeType is FunctionType) {
pointeeType.returnType.getStringRepresentation() + " (*)(" + "void*" // TODO
pointeeType.parameterTypes.map { it.getStringRepresentation() }.joinToString(", ") + ")"
} else { } else {
pointeeType.getStringRepresentation() + "*" pointeeType.getStringRepresentation() + "*"
} }
@@ -370,10 +369,6 @@ class StubGenerator(
if (pointeeType.unwrapTypedefs() is VoidType) { if (pointeeType.unwrapTypedefs() is VoidType) {
val info = TypeInfo.Pointer("COpaque") val info = TypeInfo.Pointer("COpaque")
TypeMirror.ByValue("COpaquePointerVar", info, "COpaquePointer") TypeMirror.ByValue("COpaquePointerVar", info, "COpaquePointer")
} else if (pointeeType is FunctionType) {
val kotlinName = pointeeType.kotlinName
val info = TypeInfo.Pointer("CFunction<$kotlinName>")
TypeMirror.ByValue("CFunctionPointerVar<$kotlinName>", info, "CFunctionPointer<$kotlinName>")
} else { } else {
val pointeeMirror = mirror(pointeeType) val pointeeMirror = mirror(pointeeType)
val info = TypeInfo.Pointer(pointeeMirror.pointedTypeName) val info = TypeInfo.Pointer(pointeeMirror.pointedTypeName)
@@ -387,6 +382,8 @@ class StubGenerator(
byRefTypeMirror("CArray<${elemMirror.pointedTypeName}>") byRefTypeMirror("CArray<${elemMirror.pointedTypeName}>")
} }
is FunctionType -> byRefTypeMirror("CFunction<${type.kotlinName}>")
is Typedef -> { is Typedef -> {
val baseType = mirror(type.def.aliased) val baseType = mirror(type.def.aliased)
val name = type.def.name val name = type.def.name
@@ -793,6 +790,8 @@ class StubGenerator(
is UInt32Type -> "UInt32" is UInt32Type -> "UInt32"
is IntPtrType, is UIntPtrType, // TODO is IntPtrType, is UIntPtrType, // TODO
is PointerType -> "Pointer" is PointerType -> "Pointer"
is Int64Type -> "SInt64"
is UInt64Type -> "UInt64"
is ConstArrayType -> getFfiStructType( is ConstArrayType -> getFfiStructType(
Array(type.length.toInt(), { type.elemType }).toList() Array(type.length.toInt(), { type.elemType }).toList()
) )
@@ -800,7 +799,7 @@ class StubGenerator(
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(type.kotlinName)
} }
getFfiStructType(def.fields.map { it.type }) getFfiStructType(def.fields.map { it.type })
} }
@@ -864,8 +863,15 @@ class StubGenerator(
private fun generateJvmFunctionType(type: FunctionType, name: String) { private fun generateJvmFunctionType(type: FunctionType, name: String) {
val kotlinFunctionType = getKotlinFunctionType(type) val kotlinFunctionType = getKotlinFunctionType(type)
val constructorArgs = listOf(getRetValFfiType(type.returnType)) + val constructorArgs = try {
type.parameterTypes.map { getArgFfiType(it) } listOf(getRetValFfiType(type.returnType)) +
type.parameterTypes.map { getArgFfiType(it) }
} catch (e: Throwable) {
println("Warning: cannot generate definition for function type $name")
out("object $name : CFunctionType {}")
return
}
val constructorArgsStr = constructorArgs.joinToString(", ") val constructorArgsStr = constructorArgs.joinToString(", ")
@@ -1198,7 +1204,7 @@ class StubGenerator(
"$pkgName.externals.${func.name}" "$pkgName.externals.${func.name}"
} }
val functionName = "Java_" + funcFullName.replace("_", "_1").replace('.', '_').replace("$", "_00024") val functionName = "Java_" + funcFullName.replace("_", "_1").replace('.', '_').replace("$", "_00024")
"JNIEXPORT $cReturnType JNICALL $functionName (JNIEnv *env, jobject obj$joinedParameters)" "JNIEXPORT $cReturnType JNICALL $functionName (JNIEnv *jniEnv, jobject externalsObj$joinedParameters)"
} }
KotlinPlatform.NATIVE -> { KotlinPlatform.NATIVE -> {
val joinedParameters = parameters.joinToString(", ") val joinedParameters = parameters.joinToString(", ")