Pyjnius: Konstruktor konnte nicht gefunden werden, wenn mehrere (überladene) Konstruktoren vorhanden sind

Erstellt am 22. Okt. 2020  ·  8Kommentare  ·  Quelle: kivy/pyjnius

Fehler mit pyjnius beim Umgang mit einer Java-Klasse mit mehreren Konstruktoren gefunden.

Wenn ich den folgenden Java-Code ausgeführt habe, ruft die Hauptmethode den 2. Konstruktor auf und wird ordnungsgemäß beendet.
Wenn ich den folgenden Python-Code ausführe, wird gemeldet, dass der Konstruktor nicht gefunden wurde.
(jnius.JavaException: No constructor matching your arguments, available: ['(ILjava/lang/String;)V', '(ILjava/lang/String;Ljava/lang/Object;[I)V'])
Aber wenn ich den ersten Konstruktor im Java-Code entfernt habe, kann mein Python-Code mit pyjnius den einzigen Konstruktor korrekt finden und elegant beenden.

Java-Klasse

public class SampleJavaClass {
    public SampleJavaClass( int arg1, String arg2, int arg3, Object arg4, int... arg5 ) {
    System.out.println("arg1: " + Integer.toString(arg1));
        System.out.println("arg2: " + arg2);
        System.out.println("arg3: " + arg3);
        System.out.println("arg3: " + arg4);
        System.out.println("arg4: " + arg5.toString());
    }

    // the constructor plans to use
    public SampleJavaClass (int arg1, String arg2, Object arg3, int... arg4) {
        System.out.println("arg1: " + Integer.toString(arg1));
        System.out.println("arg2: " + arg2);
        System.out.println("arg3: " + arg3);
        System.out.println("arg4: " + arg4.toString());
    }

    public static void main(String[] args) {
        SampleJavaClass test = new SampleJavaClass(1, "var2", null, 4);
    }
}

Python-Code mit pyjnius

import os
currentPath = os.getcwd()
classpath = currentPath + "/SampleJavaClass.class"
import jnius_config
jnius_config.set_classpath('.', classpath)
from jnius import autoclass

def main():
    SampleJavaClass = autoclass("SampleJavaClass")
    SampleJavaClass(1, "var2", None, 4)
    print("Execution finished!")


if __name__ == "__main__":
    main()

Hilfreichster Kommentar

Wenn pyjnius eine Methode oder einen Konstruktor aufruft, prüft es zuerst, ob es 0, 1 oder mehrere Konstruktoren oder Methoden mit dem angegebenen Namen gibt. Wenn es nur 1 gibt, macht es immer den Anruf und hofft auf das Beste. Wenn es mehrere gibt, führt es diesen Bewertungsprozess durch, um zu entscheiden, ob jeder akzeptabel ist oder nicht. Hoffentlich ist nur einer akzeptabel; wenn nicht, wird ein Fehler ausgegeben.

In diesem Fall werden beide abgelehnt, da Konstruktoren inakzeptabel sind. Durch die Verwendung eines Signaturhinweises wird das Problem umgangen, indem der Bewertungsprozess übersprungen wird. Der Signaturhinweis ist ein guter Workaround.

Für dieses Problem habe ich mir den Code genauer angesehen und festgestellt, dass es tatsächlich einen Fehler gibt, der dazu führt, dass dies fehlschlägt. Und zum Glück ist es eine einfache Lösung. Ich werde gleich eine PR mit einem Unit-Test machen.

Alle 8 Kommentare

Haben Sie versucht, einen Konstruktor-Signaturhinweis zu verwenden?

Ein Beispiel finden Sie unter https://github.com/kivy/pyjnius/blob/307659b13c1e5583fcb25603b7d3732265ffd4a0/tests/test_constructor.py#L54 .

Wenn pyjnius eine Methode oder einen Konstruktor aufruft, prüft es zuerst, ob es 0, 1 oder mehrere Konstruktoren oder Methoden mit dem angegebenen Namen gibt. Wenn es nur 1 gibt, macht es immer den Anruf und hofft auf das Beste. Wenn es mehrere gibt, führt es diesen Bewertungsprozess durch, um zu entscheiden, ob jeder akzeptabel ist oder nicht. Hoffentlich ist nur einer akzeptabel; wenn nicht, wird ein Fehler ausgegeben.

In diesem Fall werden beide abgelehnt, da Konstruktoren inakzeptabel sind. Durch die Verwendung eines Signaturhinweises wird das Problem umgangen, indem der Bewertungsprozess übersprungen wird. Der Signaturhinweis ist ein guter Workaround.

Für dieses Problem habe ich mir den Code genauer angesehen und festgestellt, dass es tatsächlich einen Fehler gibt, der dazu führt, dass dies fehlschlägt. Und zum Glück ist es eine einfache Lösung. Ich werde gleich eine PR mit einem Unit-Test machen.

Haben Sie versucht, einen Konstruktor-Signaturhinweis zu verwenden?

Sehen

https://github.com/kivy/pyjnius/blob/307659b13c1e5583fcb25603b7d3732265ffd4a0/tests/test_constructor.py#L54

zum Beispiel.

Ich habe gerade versucht, eine Signatur hinzuzufügen, wie im folgenden Code gezeigt, aber es wurde ein Assertionsfehler ausgegeben. Wo habe ich es vermasselt?

Fehler

  File "jnius/jnius_export_class.pxi", line 270, in jnius.JavaClass.__init__
  File "jnius/jnius_export_class.pxi", line 319, in jnius.JavaClass.call_constructor
AssertionError

Python-Code mit pyjnius

import os
currentPath = os.getcwd()
classpath = currentPath + "/SampleJavaClass.class"
import jnius_config
jnius_config.set_classpath('.', classpath)
from jnius import autoclass

def main():
    SampleJavaClass = autoclass("SampleJavaClass")
    SampleJavaClass(1, "var2", None, 4, signature="(ILjava/lang/String;Ljava/lang/Object;[I)V")
    print("Execution finished!")


if __name__ == "__main__":
    main()

Hier der entsprechende Code:

            requestedDefn = kwargs.pop('signature', None)
            for definition, is_varargs in definitions:
                found_definitions.append(definition)
                d_ret, d_args = parse_definition(definition)
                if requestedDefn == definition:
                    assert not is_varargs
                    scores=[]
                    score=1
                    scores.append((score, definition, d_ret, d_args, args))
                    break

Warum können Signaturhinweise nicht mit variablen Argumenten verwendet werden?

Egal, ich habe es herausgefunden und habe eine Lösung dafür. Ich werde es der PR hinzufügen.

@enjoybeta Ich habe dies in der PR behoben, aber unterm Strich funktioniert die

@cmacdonald , gibt es eine andere

Nichts Besonderes - eine schnelle Java-Factory-Klasse hinzufügen, die den Varargs-Konstruktor aufruft?

Wie auch immer, ich schlage vor, dass wir das Problem schließen können, da die nächste Jnius-Version den Fehler behebt.

Gute Idee! Eine Factory-Methode kann sich darum kümmern, wenn das Ändern dieses Quellcodes eine Option ist. Wenn nicht, können sie eine separate Hilfsprogrammklasse erstellen, die dies für sie erledigt.

Zugegeben, wir können dieses Thema jetzt schließen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen