Don't generate functional types for functions with long signatures (#2349)
The K/N stdlib doesn't contain basic classes (e.g. Functon0, Function1 etc) for functional types with >22 parameters. So we cannot convert functional pointers with such signatures into Kotlin functional types and have to replace them with opaque pointers. Fix for GitHub issue #2334.
This commit is contained in:
+18
-3
@@ -77,7 +77,7 @@ private class ObjCCategoryImpl(
|
|||||||
override val properties = mutableListOf<ObjCProperty>()
|
override val properties = mutableListOf<ObjCProperty>()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
internal class NativeIndexImpl(val library: NativeLibrary, val verbose: Boolean = false) : NativeIndex() {
|
||||||
|
|
||||||
private sealed class DeclarationID {
|
private sealed class DeclarationID {
|
||||||
data class USR(val usr: String) : DeclarationID()
|
data class USR(val usr: String) : DeclarationID()
|
||||||
@@ -154,6 +154,12 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
|||||||
|
|
||||||
override lateinit var includedHeaders: List<HeaderId>
|
override lateinit var includedHeaders: List<HeaderId>
|
||||||
|
|
||||||
|
private fun log(message: String) {
|
||||||
|
if (verbose) {
|
||||||
|
println(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getDeclarationId(cursor: CValue<CXCursor>): DeclarationID {
|
private fun getDeclarationId(cursor: CValue<CXCursor>): DeclarationID {
|
||||||
val usr = clang_getCursorUSR(cursor).convertAndDispose()
|
val usr = clang_getCursorUSR(cursor).convertAndDispose()
|
||||||
if (usr == "") {
|
if (usr == "") {
|
||||||
@@ -618,6 +624,15 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
|||||||
} else {
|
} else {
|
||||||
val returnType = convertType(clang_getResultType(type))
|
val returnType = convertType(clang_getResultType(type))
|
||||||
val numArgs = clang_getNumArgTypes(type)
|
val numArgs = clang_getNumArgTypes(type)
|
||||||
|
|
||||||
|
// Ignore functions with long signatures since we have no basic class for such functional types in the stdlib.
|
||||||
|
// TODO: Remove this limitation when functional types with long signatures are supported.
|
||||||
|
if (numArgs > 22) {
|
||||||
|
log("Warning: cannot generate a Kotlin functional type for a pointer to a function with more than 22 parameters. " +
|
||||||
|
"An opaque pointer will be used instead.")
|
||||||
|
return VoidType
|
||||||
|
}
|
||||||
|
|
||||||
val paramTypes = (0..numArgs - 1).map {
|
val paramTypes = (0..numArgs - 1).map {
|
||||||
convertType(clang_getArgType(type, it))
|
convertType(clang_getArgType(type, it))
|
||||||
}
|
}
|
||||||
@@ -902,8 +917,8 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildNativeIndexImpl(library: NativeLibrary): NativeIndex {
|
fun buildNativeIndexImpl(library: NativeLibrary, verbose: Boolean): NativeIndex {
|
||||||
val result = NativeIndexImpl(library)
|
val result = NativeIndexImpl(library, verbose)
|
||||||
indexDeclarations(result)
|
indexDeclarations(result)
|
||||||
findMacros(result)
|
findMacros(result)
|
||||||
return result
|
return result
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ data class NativeLibrary(val includes: List<String>,
|
|||||||
/**
|
/**
|
||||||
* Retrieves the definitions from given C header file using given compiler arguments (e.g. defines).
|
* Retrieves the definitions from given C header file using given compiler arguments (e.g. defines).
|
||||||
*/
|
*/
|
||||||
fun buildNativeIndex(library: NativeLibrary): NativeIndex = buildNativeIndexImpl(library)
|
fun buildNativeIndex(library: NativeLibrary, verbose: Boolean): NativeIndex = buildNativeIndexImpl(library, verbose)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class describes the IR of definitions from C header file(s).
|
* This class describes the IR of definitions from C header file(s).
|
||||||
|
|||||||
+1
-1
@@ -241,7 +241,7 @@ private fun processCLib(args: Array<String>): Array<String>? {
|
|||||||
target = tool.target
|
target = tool.target
|
||||||
)
|
)
|
||||||
|
|
||||||
val nativeIndex = buildNativeIndex(library)
|
val nativeIndex = buildNativeIndex(library, verbose)
|
||||||
|
|
||||||
val gen = StubGenerator(nativeIndex, configuration, libName, generateShims, verbose, flavor, imports)
|
val gen = StubGenerator(nativeIndex, configuration, libName, generateShims, verbose, flavor, imports)
|
||||||
|
|
||||||
|
|||||||
@@ -2850,7 +2850,7 @@ task interop_bitfields(type: RunInteropKonanTest) {
|
|||||||
task interop_funptr(type: RunInteropKonanTest) {
|
task interop_funptr(type: RunInteropKonanTest) {
|
||||||
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
|
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
|
||||||
expectedFail = (project.testTarget == 'linux_mips32') // fails because of big-endiannes
|
expectedFail = (project.testTarget == 'linux_mips32') // fails because of big-endiannes
|
||||||
goldValue = "42\n17\n1\n0\n"
|
goldValue = "42\n17\n1\n0\n42\n42\n"
|
||||||
source = "interop/basics/funptr.kt"
|
source = "interop/basics/funptr.kt"
|
||||||
interop = 'cfunptr'
|
interop = 'cfunptr'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,4 +59,36 @@ static unsigned int getMaxUInt(void) {
|
|||||||
|
|
||||||
static typeof(&getMaxUInt) getMaxUIntGetter() {
|
static typeof(&getMaxUInt) getMaxUIntGetter() {
|
||||||
return &getMaxUInt;
|
return &getMaxUInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (*longSignatureFunctionPtrType)(
|
||||||
|
int, int, int, int, int, int, int, int, int, int, int, int,
|
||||||
|
int, int, int, int, int, int, int, int, int, int, int
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef int (*notSoLongSignatureFunctionPtrType)(
|
||||||
|
int, int, int, int, int, int, int, int, int, int, int,
|
||||||
|
int, int, int, int, int, int, int, int, int, int, int
|
||||||
|
);
|
||||||
|
|
||||||
|
static int longSignatureFunction(
|
||||||
|
int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11, int p12,
|
||||||
|
int p13, int p14, int p15, int p16, int p17, int p18, int p19, int p20, int p21, int p22, int p23
|
||||||
|
) {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int notSoLongSignatureFunction(
|
||||||
|
int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9, int p10, int p11, int p12,
|
||||||
|
int p13, int p14, int p15, int p16, int p17, int p18, int p19, int p20, int p21, int p22
|
||||||
|
) {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
static longSignatureFunctionPtrType getLongSignatureFunctionPtr() {
|
||||||
|
return &longSignatureFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
static notSoLongSignatureFunctionPtrType getNotSoLongSignatureFunctionPtr() {
|
||||||
|
return ¬SoLongSignatureFunction;
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,11 @@ import kotlinx.cinterop.*
|
|||||||
import cfunptr.*
|
import cfunptr.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
typealias NotSoLongSignatureFunction = (
|
||||||
|
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
|
||||||
|
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int
|
||||||
|
) -> Int
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val atoiPtr = getAtoiPtr()!!
|
val atoiPtr = getAtoiPtr()!!
|
||||||
|
|
||||||
@@ -31,6 +36,11 @@ fun main(args: Array<String>) {
|
|||||||
printIntPtr(isIntPositivePtr(-42).ifThenOneElseZero())
|
printIntPtr(isIntPositivePtr(-42).ifThenOneElseZero())
|
||||||
|
|
||||||
assertEquals(getMaxUIntGetter()!!(), UInt.MAX_VALUE)
|
assertEquals(getMaxUIntGetter()!!(), UInt.MAX_VALUE)
|
||||||
|
|
||||||
|
val longSignaturePtr: COpaquePointer? = getLongSignatureFunctionPtr()
|
||||||
|
val notSoLongSignaturePtr: CPointer<CFunction<NotSoLongSignatureFunction>>? = getNotSoLongSignatureFunctionPtr()
|
||||||
|
printIntPtr(notSoLongSignaturePtr!!.invoke(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
|
||||||
|
printIntPtr(notSoLongSignatureFunction(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Boolean.ifThenOneElseZero() = if (this) 1 else 0
|
fun Boolean.ifThenOneElseZero() = if (this) 1 else 0
|
||||||
Reference in New Issue
Block a user