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:
Ilya Matveev
2018-11-21 11:21:37 +07:00
committed by GitHub
parent 77897ba712
commit 1ec506d0b1
6 changed files with 63 additions and 6 deletions
@@ -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
@@ -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).
@@ -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)
+1 -1
View File
@@ -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 &notSoLongSignatureFunction;
}
@@ -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