Fix few problems in generation of C bindings. (#1453)
This commit is contained in:
+46
-13
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
|
|
||||||
private enum class ScopeKind {
|
private enum class ScopeKind {
|
||||||
TOP,
|
TOP,
|
||||||
@@ -87,7 +88,27 @@ private val cKeywords = setOf(
|
|||||||
"_Alignas", "_Alignof", "_Atomic", "_Generic", "_Noreturn", "_Static_assert", "_Thread_local",
|
"_Alignas", "_Alignof", "_Atomic", "_Generic", "_Noreturn", "_Static_assert", "_Thread_local",
|
||||||
// Not exactly keywords, but reserved or standard-defined.
|
// Not exactly keywords, but reserved or standard-defined.
|
||||||
"and", "not", "or", "xor",
|
"and", "not", "or", "xor",
|
||||||
"bool", "complex", "imaginary"
|
"bool", "complex", "imaginary",
|
||||||
|
|
||||||
|
// C++ keywords not listed above.
|
||||||
|
"alignas", "alignof", "and_eq", "asm",
|
||||||
|
"bitand", "bitor", "bool",
|
||||||
|
"catch", "char16_t", "char32_t", "class", "compl", "constexpr", "const_cast",
|
||||||
|
"decltype", "delete", "dynamic_cast",
|
||||||
|
"explicit", "export",
|
||||||
|
"false", "friend",
|
||||||
|
"inline",
|
||||||
|
"mutable",
|
||||||
|
"namespace", "new", "noexcept", "not_eq", "nullptr",
|
||||||
|
"operator", "or_eq",
|
||||||
|
"private", "protected", "public",
|
||||||
|
"reinterpret_cast",
|
||||||
|
"static_assert",
|
||||||
|
"template", "this", "thread_local", "throw", "true", "try", "typeid", "typename",
|
||||||
|
"using",
|
||||||
|
"virtual",
|
||||||
|
"wchar_t",
|
||||||
|
"xor_eq"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val cnameAnnotation = FqName("konan.internal.CName")
|
private val cnameAnnotation = FqName("konan.internal.CName")
|
||||||
@@ -253,6 +274,9 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
val isClass = declaration is ClassDescriptor && declaration.kind != ClassKind.ENUM_ENTRY
|
val isClass = declaration is ClassDescriptor && declaration.kind != ClassKind.ENUM_ENTRY
|
||||||
val isEnumEntry = declaration is ClassDescriptor && declaration.kind == ClassKind.ENUM_ENTRY
|
val isEnumEntry = declaration is ClassDescriptor && declaration.kind == ClassKind.ENUM_ENTRY
|
||||||
|
|
||||||
|
|
||||||
|
fun KotlinType.includeToSignature() = !this.isUnit()
|
||||||
|
|
||||||
fun makeCFunctionSignature(shortName: Boolean): List<Pair<String, ClassDescriptor>> {
|
fun makeCFunctionSignature(shortName: Boolean): List<Pair<String, ClassDescriptor>> {
|
||||||
if (!isFunction) {
|
if (!isFunction) {
|
||||||
throw Error("only for functions")
|
throw Error("only for functions")
|
||||||
@@ -267,9 +291,11 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
else -> uniqueName(original, shortName) to TypeUtils.getClassDescriptor(original.returnType!!)!!
|
else -> uniqueName(original, shortName) to TypeUtils.getClassDescriptor(original.returnType!!)!!
|
||||||
}
|
}
|
||||||
val uniqueNames = owner.paramsToUniqueNames(original.explicitParameters)
|
val uniqueNames = owner.paramsToUniqueNames(original.explicitParameters)
|
||||||
val params = ArrayList(original.explicitParameters.mapIndexed { idx, it ->
|
val params = ArrayList(original.explicitParameters
|
||||||
uniqueNames[idx] to TypeUtils.getClassDescriptor(it.type)!!
|
.filter { it.type.includeToSignature() }
|
||||||
})
|
.map { it ->
|
||||||
|
uniqueNames[it]!! to TypeUtils.getClassDescriptor(it.type)!!
|
||||||
|
})
|
||||||
return listOf(returned) + params
|
return listOf(returned) + params
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,9 +311,11 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
else -> original.returnType!!
|
else -> original.returnType!!
|
||||||
}
|
}
|
||||||
val returnedClass = TypeUtils.getClassDescriptor(returnedType)!!
|
val returnedClass = TypeUtils.getClassDescriptor(returnedType)!!
|
||||||
val params = ArrayList(original.allParameters.map {
|
val params = ArrayList(original.allParameters
|
||||||
owner.translateTypeBridge(TypeUtils.getClassDescriptor(it.type)!!)
|
.filter { it.type.includeToSignature() }
|
||||||
})
|
.map {
|
||||||
|
owner.translateTypeBridge(TypeUtils.getClassDescriptor(it.type)!!)
|
||||||
|
})
|
||||||
if (owner.isMappedToReference(returnedClass) || owner.isMappedToString(returnedClass)) {
|
if (owner.isMappedToReference(returnedClass) || owner.isMappedToString(returnedClass)) {
|
||||||
params += "KObjHeader**"
|
params += "KObjHeader**"
|
||||||
}
|
}
|
||||||
@@ -359,7 +387,9 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
"((${owner.translateType(clazz)}){ .pinned = CreateStablePointer(${name})})"
|
"((${owner.translateType(clazz)}){ .pinned = CreateStablePointer(${name})})"
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
assert(clazz.isValueType)
|
assert(clazz.isValueType) {
|
||||||
|
println(clazz.toString())
|
||||||
|
}
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,6 +464,9 @@ private class ExportedElement(val kind: ElementKind,
|
|||||||
val original = descriptor.original
|
val original = descriptor.original
|
||||||
addUsedType(original.correspondingProperty.type, set)
|
addUsedType(original.correspondingProperty.type, set)
|
||||||
}
|
}
|
||||||
|
is ClassDescriptor -> {
|
||||||
|
set += descriptor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,16 +496,16 @@ internal class CAdapterGenerator(
|
|||||||
private lateinit var outputStreamWriter: PrintWriter
|
private lateinit var outputStreamWriter: PrintWriter
|
||||||
private val paramNamesRecorded = mutableMapOf<String, Int>()
|
private val paramNamesRecorded = mutableMapOf<String, Int>()
|
||||||
|
|
||||||
internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): List<String> {
|
internal fun paramsToUniqueNames(params: List<ParameterDescriptor>): Map<ParameterDescriptor, String> {
|
||||||
paramNamesRecorded.clear()
|
paramNamesRecorded.clear()
|
||||||
return params.map {
|
return params.associate {
|
||||||
val name = translateName(it.name.asString())
|
val name = translateName(it.name.asString())
|
||||||
val count = paramNamesRecorded.getOrDefault(name, 0)
|
val count = paramNamesRecorded.getOrDefault(name, 0)
|
||||||
paramNamesRecorded[name] = count + 1
|
paramNamesRecorded[name] = count + 1
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
name
|
it to name
|
||||||
} else {
|
} else {
|
||||||
"$name${count.toString()}"
|
it to "$name${count.toString()}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -671,7 +704,7 @@ internal class CAdapterGenerator(
|
|||||||
element.isClass ->
|
element.isClass ->
|
||||||
output("/* Type for ${element.name} = */ ${element.cname}, ", indent)
|
output("/* Type for ${element.name} = */ ${element.cname}, ", indent)
|
||||||
element.isEnumEntry ->
|
element.isEnumEntry ->
|
||||||
output("/* enum entry getter ${element.name} = */ ${element.cname}_impl", indent)
|
output("/* enum entry getter ${element.name} = */ ${element.cname}_impl,", indent)
|
||||||
// TODO: handle properties.
|
// TODO: handle properties.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user