Kotlin内联功能无法正常工作

时间:2015-08-01 15:46:24

标签: kotlin qt-jambi

在使用QtJambi作为GUI工具包的项目工作时,我试图编写一个库来使连接信号和插槽更容易。我发现了以下问题。

这是我的代码:

_______________________________________________________________
|  id   |   Monday    |   Tuesday     |  Wednesday    | ...| Sunday  |
_______________________________________________________________
|   1   | 10:00:00  AM | 09:00:00  AM |  Null         |....| Null    |
|   1   | 12:00:00  AM | 01:30:00  PM |  Null         |....| Null    |
|   2   | 09:00:00  AM |  Null        |  11:00:00  AM |....| Null    |
|   2   | 11:00:00  AM |  Null        |  11:30:00  AM |....| Null    |
|   2   | 11:30:00  PM |  Null        |  01:00:00  PM |....| Null    |
|   3   | 10:00:00  AM | 06:00:00  PM |  02:00:00  PM |....| Null    |
|   3   | 10:00:00  PM | 07:30:00  PM |  02:30:00  PM |....| Null    |  

当没有预期的通用参数时,这适用于第一个连接函数。但对于第二个连接功能,当我做类似的事情时:

inline fun QSignalEmitter.Signal0.connect(
        inlineOptions(InlineOption.ONLY_LOCAL_RETURN) action: () -> Unit) {
    connect(object {
        fun execute() {
            action()
        }
    }, "execute()")
}

inline fun <reified A> QSignalEmitter.Signal1<A>.connect(
        inlineOptions(InlineOption.ONLY_LOCAL_RETURN) action: (A) -> Unit) {
    connect(object {
        fun execute(a: A) {
            action(a)
        }
    }, "execute(" + javaClass<A>().getCanonicalName() + ")")
}

我收到以下错误:

QCheckBox().toggled.connect({ print(it) })

可能的原因是什么?如何绕过它?

编辑:用法示例

Exception in thread "main" com.trolltech.qt.QNoSuchSlotException: 

Could not find slot with signature: execute(java.lang.Boolean)
Possible matching methods:
   com.TestPackage$Test$f1214d02$main$$inlined$connect$1.execute(java.lang.Object)

    at com.trolltech.qt.QSignalEmitter$AbstractSignal.connect(QSignalEmitter.java:72)
    at com.trolltech.qt.QSignalEmitter$AbstractSignal.connect(QSignalEmitter.java:132)
    at com.TestPackage$Test$f1214d02.main(Test.kt:9)
    at com.TestPackage.main(Test.kt:1)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

Kotlin Bytecode

inline fun <reified A> QSignalEmitter.Signal1<A>.connect(noinline action: (A) -> Unit) {
    connect(action, "invoke(${javaClass<A>()})")
}

fun main(args: Array<String>) {
    QApplication.initialize(args)

    val widget = QWidget()
    val button = QPushButton("Say Hello")
    button.clicked.connect {
        println("Hello World")
    }
    val layout = QFormLayout(widget)
    layout.addWidget(button)

    widget.show()
    QApplication.execStatic()
}

1 个答案:

答案 0 :(得分:1)

内联函数内的类不是专门的,因此字节码中对象的 execute具有下一个签名execute(java.lang.Object)。但是javaClass<A>()专注于connect,您提供了另一个签名:execute(java.lang.Boolean)

尝试写:

fun <A> QSignalEmitter.Signal1<A>.connect(action: (A) -> Unit) {
    connect(action, "invoke(java.lang.Object)")
}

解决方案2:

inline fun <reified A> S<A>.connect(noinline action: (A) -> Unit) {
    connect(action, "invoke(${javaClass<A>()})")
}