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>()
|
||||
}
|
||||
|
||||
internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
||||
internal class NativeIndexImpl(val library: NativeLibrary, val verbose: Boolean = false) : NativeIndex() {
|
||||
|
||||
private sealed class 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>
|
||||
|
||||
private fun log(message: String) {
|
||||
if (verbose) {
|
||||
println(message)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeclarationId(cursor: CValue<CXCursor>): DeclarationID {
|
||||
val usr = clang_getCursorUSR(cursor).convertAndDispose()
|
||||
if (usr == "") {
|
||||
@@ -618,6 +624,15 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
||||
} else {
|
||||
val returnType = convertType(clang_getResultType(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 {
|
||||
convertType(clang_getArgType(type, it))
|
||||
}
|
||||
@@ -902,8 +917,8 @@ internal class NativeIndexImpl(val library: NativeLibrary) : NativeIndex() {
|
||||
|
||||
}
|
||||
|
||||
fun buildNativeIndexImpl(library: NativeLibrary): NativeIndex {
|
||||
val result = NativeIndexImpl(library)
|
||||
fun buildNativeIndexImpl(library: NativeLibrary, verbose: Boolean): NativeIndex {
|
||||
val result = NativeIndexImpl(library, verbose)
|
||||
indexDeclarations(result)
|
||||
findMacros(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).
|
||||
*/
|
||||
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).
|
||||
|
||||
+1
-1
@@ -241,7 +241,7 @@ private fun processCLib(args: Array<String>): Array<String>? {
|
||||
target = tool.target
|
||||
)
|
||||
|
||||
val nativeIndex = buildNativeIndex(library)
|
||||
val nativeIndex = buildNativeIndex(library, verbose)
|
||||
|
||||
val gen = StubGenerator(nativeIndex, configuration, libName, generateShims, verbose, flavor, imports)
|
||||
|
||||
|
||||
@@ -2850,7 +2850,7 @@ task interop_bitfields(type: RunInteropKonanTest) {
|
||||
task interop_funptr(type: RunInteropKonanTest) {
|
||||
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
|
||||
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"
|
||||
interop = 'cfunptr'
|
||||
}
|
||||
|
||||
@@ -59,4 +59,36 @@ static unsigned int getMaxUInt(void) {
|
||||
|
||||
static typeof(&getMaxUInt) getMaxUIntGetter() {
|
||||
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 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>) {
|
||||
val atoiPtr = getAtoiPtr()!!
|
||||
|
||||
@@ -31,6 +36,11 @@ fun main(args: Array<String>) {
|
||||
printIntPtr(isIntPositivePtr(-42).ifThenOneElseZero())
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user