Kotlin内联函数无法正常工作

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

这是我的代码:

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) 

什么是可能的原因,我怎样才能解决它?

编辑:使用示例

 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() } 

Kotlin字节码

 // ================_DefaultPackage$QtExtensions$7d5c0ac6.class ================= // class version 50.0 (50) // access flags 0x11 public final class _DefaultPackage$QtExtensions$7d5c0ac6 { // access flags 0x19 // signature <A:Ljava/lang/Object;>(Lcom/trolltech/qt/QSignalEmitter$Signal1<TA;>;Lkotlin/jvm/functions/Function1<-TA;+Lkotlin/Unit;>;)V // declaration: void connect<A>(com.trolltech.qt.QSignalEmitter$Signal1<A>, kotlin.jvm.functions.Function1<? super A, ? extends kotlin.Unit>) public final static connect(Lcom/trolltech/qt/QSignalEmitter$Signal1;Lkotlin/jvm/functions/Function1;)V @Lkotlin/inline;() // invisible @Ljet/runtime/typeinfo/JetValueParameter;(name="$receiver") // parameter 0 @Ljet/runtime/typeinfo/JetValueParameter;(name="action") // parameter 1 @Lkotlin/noinline;() // invisible, parameter 1 @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 1 L0 L1 ALOAD 0 LDC "$receiver" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V ALOAD 1 LDC "action" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V L2 LINENUMBER 9 L2 ALOAD 0 ALOAD 1 NEW java/lang/StringBuilder DUP INVOKESPECIAL java/lang/StringBuilder.<init> ()V LDC "invoke(" INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; LDC "A" INVOKESTATIC kotlin/jvm/internal/Intrinsics.reifyJavaClass (Ljava/lang/String;)V LDC Ljava/lang/Object;.class INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder; LDC ")" INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String; INVOKEVIRTUAL com/trolltech/qt/QSignalEmitter$Signal1.connect (Ljava/lang/Object;Ljava/lang/String;)V L3 LINENUMBER 10 L3 RETURN L4 LOCALVARIABLE $receiver Lcom/trolltech/qt/QSignalEmitter$Signal1; L0 L4 0 LOCALVARIABLE action Lkotlin/jvm/functions/Function1; L0 L4 1 MAXSTACK = 4 MAXLOCALS = 2 // access flags 0x19 public final static main([Ljava/lang/String;)V @Ljet/runtime/typeinfo/JetValueParameter;(name="args") // parameter 0 @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0 L0 L1 ALOAD 0 LDC "args" INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V L2 LINENUMBER 13 L2 ALOAD 0 INVOKESTATIC com/trolltech/qt/gui/QApplication.initialize ([Ljava/lang/String;)V L3 LINENUMBER 15 L3 NEW com/trolltech/qt/gui/QWidget DUP INVOKESPECIAL com/trolltech/qt/gui/QWidget.<init> ()V ASTORE 1 L4 L5 LINENUMBER 16 L5 NEW com/trolltech/qt/gui/QPushButton DUP LDC "Say Hello" INVOKESPECIAL com/trolltech/qt/gui/QPushButton.<init> (Ljava/lang/String;)V ASTORE 2 L6 L7 LINENUMBER 17 L7 ALOAD 2 CHECKCAST com/trolltech/qt/gui/QAbstractButton GETFIELD com/trolltech/qt/gui/QAbstractButton.clicked : Lcom/trolltech/qt/QSignalEmitter$Signal1; ASTORE 3 GETSTATIC _DefaultPackage$QtExtensions$7d5c0ac6$main$1.INSTANCE$ : L_DefaultPackage$QtExtensions$7d5c0ac6$main$1; CHECKCAST kotlin/jvm/functions/Function1 ASTORE 4 NOP L8 L9 L10 LINENUMBER 9 L10 ALOAD 3 ALOAD 4 NEW java/lang/StringBuilder DUP INVOKESPECIAL java/lang/StringBuilder.<init> ()V LDC "invoke(" INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; LDC Ljava/lang/Boolean;.class INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder; LDC ")" INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String; INVOKEVIRTUAL com/trolltech/qt/QSignalEmitter$Signal1.connect (Ljava/lang/Object;Ljava/lang/String;)V L11 LINENUMBER 10 L11 L12 L13 L14 LINENUMBER 20 L14 NEW com/trolltech/qt/gui/QFormLayout DUP ALOAD 1 INVOKESPECIAL com/trolltech/qt/gui/QFormLayout.<init> (Lcom/trolltech/qt/gui/QWidget;)V ASTORE 3 L15 L16 LINENUMBER 21 L16 ALOAD 3 ALOAD 2 CHECKCAST com/trolltech/qt/gui/QWidget INVOKEVIRTUAL com/trolltech/qt/gui/QFormLayout.addWidget (Lcom/trolltech/qt/gui/QWidget;)V L17 LINENUMBER 23 L17 ALOAD 1 INVOKEVIRTUAL com/trolltech/qt/gui/QWidget.show ()V L18 LINENUMBER 24 L18 INVOKESTATIC com/trolltech/qt/gui/QApplication.execStatic ()I POP L19 LINENUMBER 25 L19 RETURN L20 LOCALVARIABLE $receiver Lcom/trolltech/qt/QSignalEmitter$Signal1; L8 L12 3 LOCALVARIABLE action Lkotlin/jvm/functions/Function1; L8 L12 4 LOCALVARIABLE layout Lcom/trolltech/qt/gui/QFormLayout; L15 L20 3 LOCALVARIABLE button Lcom/trolltech/qt/gui/QPushButton; L6 L20 2 LOCALVARIABLE widget Lcom/trolltech/qt/gui/QWidget; L4 L20 1 LOCALVARIABLE args [Ljava/lang/String; L0 L20 0 MAXSTACK = 4 MAXLOCALS = 5 @Lkotlin/jvm/internal/KotlinSyntheticClass;(abiVersion=23, kind=Lkotlin/jvm/internal/KotlinSyntheticClass$Kind;.PACKAGE_PART) // access flags 0x19 public final static INNERCLASS _DefaultPackage$QtExtensions$7d5c0ac6$main$1 null null // compiled from: QtExtensions.kt // debug info: SMAP QtExtensions.kt Kotlin *S Kotlin *F + 1 QtExtensions.kt _DefaultPackage *L 1#1,25:1 *E } // ================_DefaultPackage$QtExtensions$7d5c0ac6$main$1.class ================= // class version 50.0 (50) // access flags 0x30 // signature Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function1<Ljava/lang/Boolean;Lkotlin/Unit;>; // declaration: _DefaultPackage$QtExtensions$7d5c0ac6$main$1 extends kotlin.jvm.internal.Lambda implements kotlin.jvm.functions.Function1<java.lang.Boolean, kotlin.Unit> final class _DefaultPackage$QtExtensions$7d5c0ac6$main$1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function1 { // access flags 0x41 public bridge invoke(Ljava/lang/Object;)Ljava/lang/Object; ALOAD 0 ALOAD 1 CHECKCAST java/lang/Boolean INVOKEVIRTUAL _DefaultPackage$QtExtensions$7d5c0ac6$main$1.invoke (Ljava/lang/Boolean;)V GETSTATIC kotlin/Unit.INSTANCE$ : Lkotlin/Unit; ARETURN MAXSTACK = 2 MAXLOCALS = 2 // access flags 0x11 public final invoke(Ljava/lang/Boolean;)V @Ljet/runtime/typeinfo/JetValueParameter;(name="it") // parameter 0 L0 L1 L2 LINENUMBER 18 L2 LDC "Hello World" INVOKESTATIC kotlin/io/IoPackage.println (Ljava/lang/Object;)V L3 RETURN L4 LOCALVARIABLE this L_DefaultPackage$QtExtensions$7d5c0ac6$main$1; L0 L4 0 LOCALVARIABLE it Ljava/lang/Boolean; L0 L4 1 MAXSTACK = 1 MAXLOCALS = 2 // access flags 0x0 <init>()V ALOAD 0 ICONST_1 INVOKESPECIAL kotlin/jvm/internal/Lambda.<init> (I)V RETURN MAXSTACK = 2 MAXLOCALS = 1 // access flags 0x1008 static synthetic <clinit>()V NEW _DefaultPackage$QtExtensions$7d5c0ac6$main$1 DUP INVOKESPECIAL _DefaultPackage$QtExtensions$7d5c0ac6$main$1.<init> ()V PUTSTATIC _DefaultPackage$QtExtensions$7d5c0ac6$main$1.INSTANCE$ : L_DefaultPackage$QtExtensions$7d5c0ac6$main$1; RETURN MAXSTACK = 2 MAXLOCALS = 0 // access flags 0x19 public final static L_DefaultPackage$QtExtensions$7d5c0ac6$main$1; INSTANCE$ @Lkotlin/jvm/internal/KotlinSyntheticClass;(abiVersion=23, kind=Lkotlin/jvm/internal/KotlinSyntheticClass$Kind;.ANONYMOUS_FUNCTION) OUTERCLASS _DefaultPackage$QtExtensions$7d5c0ac6 main ([Ljava/lang/String;)V // access flags 0x19 public final static INNERCLASS _DefaultPackage$QtExtensions$7d5c0ac6$main$1 null null // compiled from: QtExtensions.kt } // ================_DefaultPackage.class ================= // class version 50.0 (50) // access flags 0x11 public final class _DefaultPackage { // access flags 0x8 static <clinit>()V LDC L_DefaultPackage;.class INVOKESTATIC kotlin/jvm/internal/Reflection.createKotlinPackage (Ljava/lang/Class;)Lkotlin/reflect/KPackage; PUTSTATIC _DefaultPackage.$kotlinPackage : Lkotlin/reflect/KPackage; RETURN MAXSTACK = 1 MAXLOCALS = 0 // access flags 0x1019 public final static synthetic Lkotlin/reflect/KPackage; $kotlinPackage // access flags 0x19 public final static main([Ljava/lang/String;)V @Ljet/runtime/typeinfo/JetValueParameter;(name="args") // parameter 0 @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0 L0 L1 LINENUMBER 1 L1 ALOAD 0 INVOKESTATIC _DefaultPackage$QtExtensions$7d5c0ac6.main ([Ljava/lang/String;)V RETURN L2 LOCALVARIABLE args [Ljava/lang/String; L0 L2 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x19 // signature <A:Ljava/lang/Object;>(Lcom/trolltech/qt/QSignalEmitter$Signal1<TA;>;Lkotlin/jvm/functions/Function1<-TA;+Lkotlin/Unit;>;)V // declaration: void connect<A>(com.trolltech.qt.QSignalEmitter$Signal1<A>, kotlin.jvm.functions.Function1<? super A, ? extends kotlin.Unit>) public final static connect(Lcom/trolltech/qt/QSignalEmitter$Signal1;Lkotlin/jvm/functions/Function1;)V @Lkotlin/inline;() // invisible @Ljet/runtime/typeinfo/JetValueParameter;(name="$receiver") // parameter 0 @Ljet/runtime/typeinfo/JetValueParameter;(name="action") // parameter 1 @Lkotlin/noinline;() // invisible, parameter 1 @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 1 L0 L1 LINENUMBER 1 L1 ALOAD 0 ALOAD 1 INVOKESTATIC _DefaultPackage$QtExtensions$7d5c0ac6.connect (Lcom/trolltech/qt/QSignalEmitter$Signal1;Lkotlin/jvm/functions/Function1;)V RETURN L2 LOCALVARIABLE $receiver Lcom/trolltech/qt/QSignalEmitter$Signal1; L0 L2 0 LOCALVARIABLE action Lkotlin/jvm/functions/Function1; L0 L2 1 MAXSTACK = 2 MAXLOCALS = 2 @Lkotlin/jvm/internal/KotlinPackage;(abiVersion=23, data={"V\u0004)!Q.Y5o\u0015\u0011\u0009'oZ:\u000b\u000b\u0005\u0013(/Y=\u000b\r-|G\u000f\\5o\u0015\u0019\u0019FO]5oO*!QK\\5u\u0015\u0011Q\u0017M^1\u000b\u00091\u000cgn\u001a\u0006&?\u0012+gY;miB\u000b7m[1hK\u0012\nF/\u0012=uK:\u001c\u0018n\u001c8tI]\"Wg\u0019\u0019bGZR\u0011!\u0011\u0006\u0004\u0003:L(bB*jO:\u000cG.\r\u0006\u000f#NKwM\\1m\u000b6LG\u000f^3s\u0015\r\u0019w.\u001c\u0006\niJ|G\u000e\u001c;fG\"T!!\u001d;\u000b\u000f\r|gN\\3di*1\u0011m\u0019;j_:T\u0011BR;oGRLwN\\\u0019\u000b-E\u001b\u0016n\u001a8bY\u0016k\u0017\u000e\u001e;fe\u0012\u001a\u0016n\u001a8bYFR1A\u001b<n\u0015%1WO\\2uS>t7\u000f\u001e\u0006\u0003!\rQa\u0001\u0003\u0001\u0011\u0005a\u0001!B\u0002\u0005\u0001!\u0011A\u0002A\u0003\u0004\u0009\u0001A)\u0001\u0004\u0001\u0006\u0003!\u0019QA\u0001\u0003\u0003\u0011\u000f)!\u0001\"\u0002\u0009\u0005\u0015\u0019A\u0001\u0001\u0005\u0006\u0019\u0001)\u0011\u0001#\u0004\u0006\u0005\u0011!\u0001bB\u0003\u0003\u0009\u0013Ay!B\u0002\u0005\u000b!1A\u0002A\u0003\u0004\u0009\u0017AY\u0001\u0004\u0001\u0006\u0007\u0011\u0001\u0001\"\u0003\u0007\u0001\u000b\u0009!Q\u0001c\u0005\u0006\u0005\u0011\u0001\u0001BC\u0003\u0003\u0009\u001fA)\"\u0002\u0002\u0005\u0011!IQ1\u0007\u0003\u00011\u0001i*\u0002\u0002\u0001\u0009\u000251Q!\u0001E\u0001\u0013\rI!!B\u0001\u0009\u0003A\u001b\u0001!\u0009\u0002\u0006\u0003!\r\u0011k\u0001\u0004\u0005\u0001%\u0009A\u0001A\u0007\u0003\u0011\ra\u0009\u0001W\u0002\u0005\u000b?\"\u0009!E\u0004\u0005\u0001!%A\u0012A\u000b\u0004\u000b\u0005A9\u0001$\u0001\u0016\u000f\u0015\u0009\u0001BB\u0005\u0005\u0013\r)!\u0001\"\u0001\u0009\u0001aAQt\u0004C\u0001\u0011#i1\"B\u0001\u0009\u000e%!\u0011bA\u0003\u0003\u0009\u0003A\u0001!C\u0002\n\u0005\u0015\u0009\u00012\u0001)\u0004\u0002\u0005\u0012Q!\u0001E\u0002#\u000e9A\u0001C\u0005\u0002\u0009\u0001i\u0011\u0001C\u0004\u000e\u0003!E\u0001l\u0001\u0003"}) // compiled from: QtExtensions.kt } 

内联函数中的类不专门,所以对象在字节码中的execute(java.lang.Object)具有下一个签名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>()})") }