[C Interop] Use CCall annotation for global getters and setters. (#3420)
This commit is contained in:
@@ -4,7 +4,11 @@ package kotlinx.cinterop.internal
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class CStruct(val spelling: String)
|
||||
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@Target(
|
||||
AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.PROPERTY_GETTER,
|
||||
AnnotationTarget.PROPERTY_SETTER
|
||||
)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
public annotation class CCall(val id: String) {
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package org.jetbrains.kotlin.native.interop.gen
|
||||
|
||||
import org.jetbrains.kotlin.native.interop.indexer.FunctionDecl
|
||||
import org.jetbrains.kotlin.native.interop.indexer.GlobalDecl
|
||||
import org.jetbrains.kotlin.native.interop.indexer.VoidType
|
||||
import org.jetbrains.kotlin.native.interop.indexer.unwrapTypedefs
|
||||
|
||||
internal data class CCalleeWrapper(val lines: List<String>)
|
||||
|
||||
/**
|
||||
* Some functions don't have an address (e.g. macros-based or builtins).
|
||||
* To solve this problem we generate a wrapper function.
|
||||
*/
|
||||
internal class CWrappersGenerator(private val context: StubIrContext) {
|
||||
|
||||
private var currentFunctionWrapperId = 0
|
||||
|
||||
private val packageName =
|
||||
context.configuration.pkgName.replace(INVALID_CLANG_IDENTIFIER_REGEX, "_")
|
||||
|
||||
private fun generateFunctionWrapperName(functionName: String): String {
|
||||
return "${packageName}_${functionName}_wrapper${currentFunctionWrapperId++}"
|
||||
}
|
||||
|
||||
private fun bindSymbolToFunction(symbol: String, function: String): List<String> = listOf(
|
||||
"const void* $symbol __asm(${symbol.quoteAsKotlinLiteral()});",
|
||||
"const void* $symbol = &$function;"
|
||||
)
|
||||
|
||||
private data class Parameter(val type: String, val name: String)
|
||||
|
||||
private fun createWrapper(
|
||||
symbolName: String,
|
||||
wrapperName: String,
|
||||
returnType: String,
|
||||
parameters: List<Parameter>,
|
||||
body: String
|
||||
): List<String> = listOf(
|
||||
"__attribute__((always_inline))",
|
||||
"$returnType $wrapperName(${parameters.joinToString { "${it.type} ${it.name}" }}) {",
|
||||
body,
|
||||
"}",
|
||||
*bindSymbolToFunction(symbolName, wrapperName).toTypedArray()
|
||||
)
|
||||
|
||||
fun generateCCalleeWrapper(function: FunctionDecl, symbolName: String): CCalleeWrapper =
|
||||
if (function.isVararg) {
|
||||
CCalleeWrapper(bindSymbolToFunction(symbolName, function.name))
|
||||
} else {
|
||||
val wrapperName = generateFunctionWrapperName(function.name)
|
||||
|
||||
val returnType = function.returnType.getStringRepresentation()
|
||||
val parameters = function.parameters.mapIndexed { index, parameter ->
|
||||
Parameter(parameter.type.getStringRepresentation(), "p$index")
|
||||
}
|
||||
val callExpression = "${function.name}(${parameters.joinToString { it.name }});"
|
||||
val wrapperBody = if (function.returnType.unwrapTypedefs() is VoidType) {
|
||||
callExpression
|
||||
} else {
|
||||
"return $callExpression"
|
||||
}
|
||||
val wrapper = createWrapper(symbolName, wrapperName, returnType, parameters, wrapperBody)
|
||||
CCalleeWrapper(wrapper)
|
||||
}
|
||||
|
||||
fun generateCGlobalGetter(globalDecl: GlobalDecl, symbolName: String): CCalleeWrapper {
|
||||
val wrapperName = generateFunctionWrapperName("${globalDecl.name}_getter")
|
||||
val returnType = globalDecl.type.getStringRepresentation()
|
||||
val wrapperBody = "return ${globalDecl.name};"
|
||||
val wrapper = createWrapper(symbolName, wrapperName, returnType, emptyList(), wrapperBody)
|
||||
return CCalleeWrapper(wrapper)
|
||||
}
|
||||
|
||||
fun generateCGlobalSetter(globalDecl: GlobalDecl, symbolName: String): CCalleeWrapper {
|
||||
val wrapperName = generateFunctionWrapperName("${globalDecl.name}_setter")
|
||||
val globalType = globalDecl.type.getStringRepresentation()
|
||||
val parameter = Parameter(globalType, "p1")
|
||||
val wrapperBody = "${globalDecl.name} = ${parameter.name};"
|
||||
val wrapper = createWrapper(symbolName, wrapperName, "void", listOf(parameter), wrapperBody)
|
||||
return CCalleeWrapper(wrapper)
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -21,6 +21,8 @@ import org.jetbrains.kotlin.native.interop.indexer.CompilationWithPCH
|
||||
import org.jetbrains.kotlin.native.interop.indexer.Language
|
||||
import org.jetbrains.kotlin.native.interop.indexer.mapFragmentIsCompilable
|
||||
|
||||
internal val INVALID_CLANG_IDENTIFIER_REGEX = "[^a-zA-Z1-9_]".toRegex()
|
||||
|
||||
class SimpleBridgeGeneratorImpl(
|
||||
private val platform: KotlinPlatform,
|
||||
private val pkgName: String,
|
||||
@@ -246,8 +248,4 @@ class SimpleBridgeGeneratorImpl(
|
||||
nativeBacked !in excludedClients
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal val INVALID_CLANG_IDENTIFIER_REGEX = "[^a-zA-Z1-9_]".toRegex()
|
||||
}
|
||||
}
|
||||
|
||||
+36
-64
@@ -4,11 +4,8 @@
|
||||
*/
|
||||
package org.jetbrains.kotlin.native.interop.gen
|
||||
|
||||
import org.jetbrains.kotlin.native.interop.gen.SimpleBridgeGeneratorImpl.Companion.INVALID_CLANG_IDENTIFIER_REGEX
|
||||
import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform
|
||||
import org.jetbrains.kotlin.native.interop.indexer.ObjCProtocol
|
||||
import org.jetbrains.kotlin.native.interop.indexer.VoidType
|
||||
import org.jetbrains.kotlin.native.interop.indexer.unwrapTypedefs
|
||||
import org.jetbrains.kotlin.native.interop.indexer.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
class BridgeBuilderResult(
|
||||
@@ -19,8 +16,6 @@ class BridgeBuilderResult(
|
||||
val excludedStubs: Set<StubIrElement>
|
||||
)
|
||||
|
||||
private data class CCalleeWrapper(val name: String, val lines: List<String>)
|
||||
|
||||
/**
|
||||
* Generates [NativeBridges] and corresponding function bodies and property accessors.
|
||||
*/
|
||||
@@ -30,6 +25,8 @@ class StubIrBridgeBuilder(
|
||||
|
||||
private val globalAddressExpressions = mutableMapOf<Pair<String, PropertyAccessor>, KotlinExpression>()
|
||||
|
||||
private val wrapperGenerator = CWrappersGenerator(context)
|
||||
|
||||
private fun getGlobalAddressExpression(cGlobalName: String, accessor: PropertyAccessor) =
|
||||
globalAddressExpressions.getOrPut(Pair(cGlobalName, accessor)) {
|
||||
simpleBridgeGenerator.kotlinToNative(
|
||||
@@ -74,13 +71,6 @@ class StubIrBridgeBuilder(
|
||||
|
||||
private val bridgeGeneratingVisitor = object : StubIrVisitor<StubContainer?, Unit> {
|
||||
|
||||
private var currentFunctionWrapperId = 0
|
||||
|
||||
private fun generateFunctionWrapperName(packageName: String, functionName: String): String {
|
||||
val validPackageName = packageName.replace(INVALID_CLANG_IDENTIFIER_REGEX, "_")
|
||||
return "${validPackageName}_${functionName}_wrapper${currentFunctionWrapperId++}"
|
||||
}
|
||||
|
||||
override fun visitClass(element: ClassStub, owner: StubContainer?) {
|
||||
element.annotations.filterIsInstance<AnnotationStub.ObjC.ExternalClass>().firstOrNull()?.let {
|
||||
if (it.protocolGetter.isNotEmpty() && element.origin is StubOrigin.ObjCProtocol) {
|
||||
@@ -116,50 +106,10 @@ class StubIrBridgeBuilder(
|
||||
?: return
|
||||
val cCallAnnotation = function.annotations.firstIsInstanceOrNull<AnnotationStub.CCall.Symbol>()
|
||||
?: return
|
||||
val cCallSymbolName = cCallAnnotation.symbolName
|
||||
val (wrapperName, wrapperLines) = generateCCalleeWrapper(origin)
|
||||
simpleBridgeGenerator.insertNativeBridge(
|
||||
function,
|
||||
emptyList(),
|
||||
listOf(
|
||||
*wrapperLines.toTypedArray(),
|
||||
"const void* $cCallSymbolName __asm(${cCallSymbolName.quoteAsKotlinLiteral()});",
|
||||
"const void* $cCallSymbolName = &$wrapperName;"
|
||||
)
|
||||
)
|
||||
val wrapper = wrapperGenerator.generateCCalleeWrapper(origin.function, cCallAnnotation.symbolName)
|
||||
simpleBridgeGenerator.insertNativeBridge(function, emptyList(), wrapper.lines)
|
||||
}
|
||||
|
||||
/**
|
||||
* Some functions don't have an address (e.g. macros-based or builtins).
|
||||
* To solve this problem we generate a wrapper function.
|
||||
*/
|
||||
private fun generateCCalleeWrapper(origin: StubOrigin.Function): CCalleeWrapper =
|
||||
if (origin.function.isVararg) {
|
||||
CCalleeWrapper(origin.function.name, emptyList())
|
||||
} else {
|
||||
val function = origin.function
|
||||
val wrapperName = generateFunctionWrapperName(context.configuration.pkgName, function.name)
|
||||
|
||||
val returnType = function.returnType.getStringRepresentation()
|
||||
val parameters = function.parameters.mapIndexed { index, parameter ->
|
||||
"p$index" to parameter.type.getStringRepresentation()
|
||||
}
|
||||
val callExpression = "${function.name}(${parameters.joinToString { it.first }});"
|
||||
val wrapperBody = if (function.returnType.unwrapTypedefs() is VoidType) {
|
||||
callExpression
|
||||
} else {
|
||||
"return $callExpression"
|
||||
}
|
||||
|
||||
val alwaysInline = "__attribute__((always_inline))"
|
||||
val lines = listOf(
|
||||
"$alwaysInline $returnType $wrapperName(${parameters.joinToString { "${it.second} ${it.first}" }}) {",
|
||||
wrapperBody,
|
||||
"}"
|
||||
)
|
||||
CCalleeWrapper(wrapperName, lines)
|
||||
}
|
||||
|
||||
override fun visitProperty(element: PropertyStub, owner: StubContainer?) {
|
||||
try {
|
||||
when (val kind = element.kind) {
|
||||
@@ -185,14 +135,11 @@ class StubIrBridgeBuilder(
|
||||
override fun visitPropertyAccessor(accessor: PropertyAccessor, owner: StubContainer?) {
|
||||
when (accessor) {
|
||||
is PropertyAccessor.Getter.SimpleGetter -> {
|
||||
if (accessor in builderResult.bridgeGenerationComponents.getterToBridgeInfo) {
|
||||
val extra = builderResult.bridgeGenerationComponents.getterToBridgeInfo.getValue(accessor)
|
||||
val typeInfo = extra.typeInfo
|
||||
val expression = if (extra.isArray) {
|
||||
val getAddressExpression = getGlobalAddressExpression(extra.cGlobalName, accessor)
|
||||
typeInfo.argFromBridged(getAddressExpression, kotlinFile, nativeBacked = accessor) + "!!"
|
||||
} else {
|
||||
typeInfo.argFromBridged(simpleBridgeGenerator.kotlinToNative(
|
||||
when (accessor) {
|
||||
in builderResult.bridgeGenerationComponents.getterToBridgeInfo -> {
|
||||
val extra = builderResult.bridgeGenerationComponents.getterToBridgeInfo.getValue(accessor)
|
||||
val typeInfo = extra.typeInfo
|
||||
propertyAccessorBridgeBodies[accessor] = typeInfo.argFromBridged(simpleBridgeGenerator.kotlinToNative(
|
||||
nativeBacked = accessor,
|
||||
returnType = typeInfo.bridgedType,
|
||||
kotlinValues = emptyList(),
|
||||
@@ -201,7 +148,12 @@ class StubIrBridgeBuilder(
|
||||
typeInfo.cToBridged(expr = extra.cGlobalName)
|
||||
}, kotlinFile, nativeBacked = accessor)
|
||||
}
|
||||
propertyAccessorBridgeBodies[accessor] = expression
|
||||
in builderResult.bridgeGenerationComponents.arrayGetterInfo -> {
|
||||
val extra = builderResult.bridgeGenerationComponents.arrayGetterInfo.getValue(accessor)
|
||||
val typeInfo = extra.typeInfo
|
||||
val getAddressExpression = getGlobalAddressExpression(extra.cGlobalName, accessor)
|
||||
propertyAccessorBridgeBodies[accessor] = typeInfo.argFromBridged(getAddressExpression, kotlinFile, nativeBacked = accessor) + "!!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,6 +197,26 @@ class StubIrBridgeBuilder(
|
||||
val getAddressExpression = getGlobalAddressExpression(accessor.cGlobalName, accessor)
|
||||
propertyAccessorBridgeBodies[accessor] = getAddressExpression
|
||||
}
|
||||
|
||||
is PropertyAccessor.Getter.ExternalGetter -> {
|
||||
if (accessor in builderResult.wrapperGenerationComponents.getterToWrapperInfo) {
|
||||
val extra = builderResult.wrapperGenerationComponents.getterToWrapperInfo.getValue(accessor)
|
||||
val cCallAnnotation = accessor.annotations.firstIsInstanceOrNull<AnnotationStub.CCall.Symbol>()
|
||||
?: error("external getter for ${extra.global.name} wasn't marked with @CCall")
|
||||
val wrapper = wrapperGenerator.generateCGlobalGetter(extra.global, cCallAnnotation.symbolName)
|
||||
simpleBridgeGenerator.insertNativeBridge(accessor, emptyList(), wrapper.lines)
|
||||
}
|
||||
}
|
||||
|
||||
is PropertyAccessor.Setter.ExternalSetter -> {
|
||||
if (accessor in builderResult.wrapperGenerationComponents.setterToWrapperInfo) {
|
||||
val extra = builderResult.wrapperGenerationComponents.setterToWrapperInfo.getValue(accessor)
|
||||
val cCallAnnotation = accessor.annotations.firstIsInstanceOrNull<AnnotationStub.CCall.Symbol>()
|
||||
?: error("external setter for ${extra.global.name} wasn't marked with @CCall")
|
||||
val wrapper = wrapperGenerator.generateCGlobalSetter(extra.global, cCallAnnotation.symbolName)
|
||||
simpleBridgeGenerator.insertNativeBridge(accessor, emptyList(), wrapper.lines)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+51
-21
@@ -8,25 +8,22 @@ import org.jetbrains.kotlin.native.interop.gen.jvm.InteropConfiguration
|
||||
import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform
|
||||
import org.jetbrains.kotlin.native.interop.indexer.*
|
||||
|
||||
/**
|
||||
* Components that are not passed via StubIr but required for bridge generation.
|
||||
*/
|
||||
class BridgeGenerationInfo(val cGlobalName: String, val typeInfo: TypeInfo)
|
||||
|
||||
/**
|
||||
* Additional components that are required to generate bridges.
|
||||
* TODO: Metadata-based interop should not depend on these components.
|
||||
*/
|
||||
interface BridgeGenerationComponents {
|
||||
|
||||
class GlobalSetterBridgeInfo(
|
||||
val cGlobalName: String,
|
||||
val typeInfo: TypeInfo
|
||||
)
|
||||
val setterToBridgeInfo: Map<PropertyAccessor.Setter, BridgeGenerationInfo>
|
||||
|
||||
class GlobalGetterBridgeInfo(
|
||||
val cGlobalName: String,
|
||||
val typeInfo: TypeInfo,
|
||||
val isArray: Boolean
|
||||
)
|
||||
val getterToBridgeInfo: Map<PropertyAccessor.Getter, BridgeGenerationInfo>
|
||||
|
||||
val setterToBridgeInfo: Map<PropertyAccessor.Setter, GlobalSetterBridgeInfo>
|
||||
|
||||
val getterToBridgeInfo: Map<PropertyAccessor.Getter, GlobalGetterBridgeInfo>
|
||||
val arrayGetterInfo: Map<PropertyAccessor.Getter, BridgeGenerationInfo>
|
||||
|
||||
val enumToTypeMirror: Map<ClassStub.Enum, TypeMirror>
|
||||
|
||||
@@ -35,13 +32,15 @@ interface BridgeGenerationComponents {
|
||||
val cStringParameters: Set<FunctionParameterStub>
|
||||
}
|
||||
|
||||
class BridgeGenerationComponentsBuilder(
|
||||
val getterToBridgeInfo: MutableMap<PropertyAccessor.Getter, BridgeGenerationComponents.GlobalGetterBridgeInfo> = mutableMapOf(),
|
||||
val setterToBridgeInfo: MutableMap<PropertyAccessor.Setter, BridgeGenerationComponents.GlobalSetterBridgeInfo> = mutableMapOf(),
|
||||
val enumToTypeMirror: MutableMap<ClassStub.Enum, TypeMirror> = mutableMapOf(),
|
||||
val wCStringParameters: MutableSet<FunctionParameterStub> = mutableSetOf(),
|
||||
val cStringParameters: MutableSet<FunctionParameterStub> = mutableSetOf()
|
||||
) {
|
||||
class BridgeGenerationComponentsBuilder {
|
||||
|
||||
val getterToBridgeInfo = mutableMapOf<PropertyAccessor.Getter, BridgeGenerationInfo>()
|
||||
val setterToBridgeInfo = mutableMapOf<PropertyAccessor.Setter, BridgeGenerationInfo>()
|
||||
val arrayGetterBridgeInfo = mutableMapOf<PropertyAccessor.Getter, BridgeGenerationInfo>()
|
||||
val enumToTypeMirror = mutableMapOf<ClassStub.Enum, TypeMirror>()
|
||||
val wCStringParameters = mutableSetOf<FunctionParameterStub>()
|
||||
val cStringParameters = mutableSetOf<FunctionParameterStub>()
|
||||
|
||||
fun build(): BridgeGenerationComponents = object : BridgeGenerationComponents {
|
||||
override val getterToBridgeInfo =
|
||||
this@BridgeGenerationComponentsBuilder.getterToBridgeInfo.toMap()
|
||||
@@ -57,6 +56,31 @@ class BridgeGenerationComponentsBuilder(
|
||||
|
||||
override val cStringParameters: Set<FunctionParameterStub> =
|
||||
this@BridgeGenerationComponentsBuilder.cStringParameters.toSet()
|
||||
|
||||
override val arrayGetterInfo: Map<PropertyAccessor.Getter, BridgeGenerationInfo> =
|
||||
this@BridgeGenerationComponentsBuilder.arrayGetterBridgeInfo.toMap()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Components that are not passed via StubIr but required for generation of wrappers.
|
||||
*/
|
||||
class WrapperGenerationInfo(val global: GlobalDecl)
|
||||
|
||||
interface WrapperGenerationComponents {
|
||||
val getterToWrapperInfo: Map<PropertyAccessor.Getter.ExternalGetter, WrapperGenerationInfo>
|
||||
val setterToWrapperInfo: Map<PropertyAccessor.Setter.ExternalSetter, WrapperGenerationInfo>
|
||||
}
|
||||
|
||||
class WrapperGenerationComponentsBuilder {
|
||||
|
||||
val getterToWrapperInfo = mutableMapOf<PropertyAccessor.Getter.ExternalGetter, WrapperGenerationInfo>()
|
||||
val setterToWrapperInfo = mutableMapOf<PropertyAccessor.Setter.ExternalSetter, WrapperGenerationInfo>()
|
||||
|
||||
fun build(): WrapperGenerationComponents = object : WrapperGenerationComponents {
|
||||
override val getterToWrapperInfo = this@WrapperGenerationComponentsBuilder.getterToWrapperInfo.toMap()
|
||||
|
||||
override val setterToWrapperInfo = this@WrapperGenerationComponentsBuilder.setterToWrapperInfo.toMap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +110,8 @@ interface StubsBuildingContext {
|
||||
|
||||
val bridgeComponentsBuilder: BridgeGenerationComponentsBuilder
|
||||
|
||||
val wrapperComponentsBuilder: WrapperGenerationComponentsBuilder
|
||||
|
||||
fun getKotlinClassFor(objCClassOrProtocol: ObjCClassOrProtocol, isMeta: Boolean = false): Classifier
|
||||
|
||||
fun getKotlinClassForPointed(structDecl: StructDecl): Classifier
|
||||
@@ -210,6 +236,8 @@ class StubsBuildingContextImpl(
|
||||
|
||||
override val bridgeComponentsBuilder = BridgeGenerationComponentsBuilder()
|
||||
|
||||
override val wrapperComponentsBuilder = WrapperGenerationComponentsBuilder()
|
||||
|
||||
override fun getKotlinClassFor(objCClassOrProtocol: ObjCClassOrProtocol, isMeta: Boolean): Classifier {
|
||||
return declarationMapper.getKotlinClassFor(objCClassOrProtocol, isMeta)
|
||||
}
|
||||
@@ -223,7 +251,8 @@ class StubsBuildingContextImpl(
|
||||
data class StubIrBuilderResult(
|
||||
val stubs: SimpleStubContainer,
|
||||
val declarationMapper: DeclarationMapper,
|
||||
val bridgeGenerationComponents: BridgeGenerationComponents
|
||||
val bridgeGenerationComponents: BridgeGenerationComponents,
|
||||
val wrapperGenerationComponents: WrapperGenerationComponents
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -285,7 +314,8 @@ class StubIrBuilder(private val context: StubIrContext) {
|
||||
return StubIrBuilderResult(
|
||||
stubs,
|
||||
buildingContext.declarationMapper,
|
||||
buildingContext.bridgeComponentsBuilder.build()
|
||||
buildingContext.bridgeComponentsBuilder.build(),
|
||||
buildingContext.wrapperComponentsBuilder.build()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+33
-12
@@ -110,9 +110,8 @@ internal class StructStubBuilder(
|
||||
val signed = field.type.isIntegerTypeSigned()
|
||||
val readBits = PropertyAccessor.Getter.ReadBits(field.offset, field.size, signed)
|
||||
val writeBits = PropertyAccessor.Setter.WriteBits(field.offset, field.size)
|
||||
// TODO: Use something instead of [GlobalGetterBridgeInfo].
|
||||
context.bridgeComponentsBuilder.getterToBridgeInfo[readBits] = BridgeGenerationComponents.GlobalGetterBridgeInfo("", typeInfo, false)
|
||||
context.bridgeComponentsBuilder.setterToBridgeInfo[writeBits] = BridgeGenerationComponents.GlobalSetterBridgeInfo("", typeInfo)
|
||||
context.bridgeComponentsBuilder.getterToBridgeInfo[readBits] = BridgeGenerationInfo("", typeInfo)
|
||||
context.bridgeComponentsBuilder.setterToBridgeInfo[writeBits] = BridgeGenerationInfo("", typeInfo)
|
||||
val kind = PropertyStub.Kind.Var(readBits, writeBits)
|
||||
PropertyStub(field.name, WrapperStubType(kotlinType), kind)
|
||||
}
|
||||
@@ -357,7 +356,7 @@ internal class FunctionStubBuilder(
|
||||
val type = WrapperStubType(KotlinTypes.any.makeNullable())
|
||||
parameters += FunctionParameterStub("variadicArguments", type, isVararg = true)
|
||||
}
|
||||
annotations = listOf(AnnotationStub.CCall.Symbol(context.generateNextUniqueId("knifunptr_") + "_${func.name}"))
|
||||
annotations = listOf(AnnotationStub.CCall.Symbol("${context.generateNextUniqueId("knifunptr_")}_${func.name}"))
|
||||
mustBeExternal = true
|
||||
}
|
||||
val functionStub = FunctionStub(
|
||||
@@ -443,22 +442,44 @@ internal class GlobalStubBuilder(
|
||||
if (unwrappedType is ArrayType) {
|
||||
kotlinType = (mirror as TypeMirror.ByValue).valueType
|
||||
val getter = PropertyAccessor.Getter.SimpleGetter()
|
||||
val extra = BridgeGenerationComponents.GlobalGetterBridgeInfo(global.name, mirror.info, isArray = true)
|
||||
context.bridgeComponentsBuilder.getterToBridgeInfo[getter] = extra
|
||||
val extra = BridgeGenerationInfo(global.name, mirror.info)
|
||||
context.bridgeComponentsBuilder.arrayGetterBridgeInfo[getter] = extra
|
||||
kind = PropertyStub.Kind.Val(getter)
|
||||
} else {
|
||||
when (mirror) {
|
||||
is TypeMirror.ByValue -> {
|
||||
kotlinType = mirror.argType
|
||||
val getter = PropertyAccessor.Getter.SimpleGetter()
|
||||
val getterExtra = BridgeGenerationComponents.GlobalGetterBridgeInfo(global.name, mirror.info, isArray = false)
|
||||
context.bridgeComponentsBuilder.getterToBridgeInfo[getter] = getterExtra
|
||||
val getter = when (context.platform) {
|
||||
KotlinPlatform.JVM -> {
|
||||
PropertyAccessor.Getter.SimpleGetter().also {
|
||||
val getterExtra = BridgeGenerationInfo(global.name, mirror.info)
|
||||
context.bridgeComponentsBuilder.getterToBridgeInfo[it] = getterExtra
|
||||
}
|
||||
}
|
||||
KotlinPlatform.NATIVE -> {
|
||||
val cCallAnnotation = AnnotationStub.CCall.Symbol("${context.generateNextUniqueId("knifunptr_")}_${global.name}_getter")
|
||||
PropertyAccessor.Getter.ExternalGetter(listOf(cCallAnnotation)).also {
|
||||
context.wrapperComponentsBuilder.getterToWrapperInfo[it] = WrapperGenerationInfo(global)
|
||||
}
|
||||
}
|
||||
}
|
||||
kind = if (global.isConst) {
|
||||
PropertyStub.Kind.Val(getter)
|
||||
} else {
|
||||
val setter = PropertyAccessor.Setter.SimpleSetter()
|
||||
val setterExtra = BridgeGenerationComponents.GlobalSetterBridgeInfo(global.name, mirror.info)
|
||||
context.bridgeComponentsBuilder.setterToBridgeInfo[setter] = setterExtra
|
||||
val setter = when (context.platform) {
|
||||
KotlinPlatform.JVM -> {
|
||||
PropertyAccessor.Setter.SimpleSetter().also {
|
||||
val setterExtra = BridgeGenerationInfo(global.name, mirror.info)
|
||||
context.bridgeComponentsBuilder.setterToBridgeInfo[it] = setterExtra
|
||||
}
|
||||
}
|
||||
KotlinPlatform.NATIVE -> {
|
||||
val cCallAnnotation = AnnotationStub.CCall.Symbol("${context.generateNextUniqueId("knifunptr_")}_${global.name}_setter")
|
||||
PropertyAccessor.Setter.ExternalSetter(listOf(cCallAnnotation)).also {
|
||||
context.wrapperComponentsBuilder.setterToWrapperInfo[it] = WrapperGenerationInfo(global)
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyStub.Kind.Var(getter, setter)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user