Pyjnius: Impossible de trouver le constructeur lorsqu'il y a plusieurs constructeurs (surchargés)

Créé le 22 oct. 2020  ·  8Commentaires  ·  Source: kivy/pyjnius

Trouvé un bogue avec pyjnius lors du traitement d'une classe Java avec plusieurs constructeurs.

Lorsque j'ai exécuté le code Java ci-dessous, la méthode principale invoquera le 2ème constructeur et se terminera normalement.
Lorsque j'exécute le code python ci-dessous, il signalera que le constructeur est introuvable.
(jnius.JavaException: No constructor matching your arguments, available: ['(ILjava/lang/String;)V', '(ILjava/lang/String;Ljava/lang/Object;[I)V'])
Mais lorsque j'ai supprimé le 1er constructeur dans le code java, mon code python avec pyjnius peut trouver correctement le seul constructeur et finir en beauté.

Classe Java

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

Code Python avec 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()

Commentaire le plus utile

Lorsque pyjnius appelle une méthode ou un constructeur, il vérifie d'abord s'il existe 0, 1 ou plusieurs constructeurs ou méthodes avec le nom donné. S'il n'y en a qu'un, il appelle toujours, en espérant le meilleur. S'il y en a plusieurs, il effectue ce processus de notation pour essayer de décider si chacun est acceptable ou non. Espérons qu'un et un seul est acceptable ; sinon, il renvoie une erreur.

Dans ce cas, il rejette les deux car les constructeurs sont inacceptables. L'utilisation d'un indice de signature contourne le problème en lui faisant sauter le processus de notation. L'indice de signature est une bonne solution de contournement.

Pour ce problème, j'ai examiné de plus près le code et j'ai découvert qu'il y avait en fait un bogue qui faisait échouer cela. Et heureusement, c'est une solution facile. Je ferai un PR avec un test unitaire dans un instant.

Tous les 8 commentaires

avez-vous essayé d'utiliser un indice de signature de constructeur ?

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

Lorsque pyjnius appelle une méthode ou un constructeur, il vérifie d'abord s'il existe 0, 1 ou plusieurs constructeurs ou méthodes avec le nom donné. S'il n'y en a qu'un, il appelle toujours, en espérant le meilleur. S'il y en a plusieurs, il effectue ce processus de notation pour essayer de décider si chacun est acceptable ou non. Espérons qu'un et un seul est acceptable ; sinon, il renvoie une erreur.

Dans ce cas, il rejette les deux car les constructeurs sont inacceptables. L'utilisation d'un indice de signature contourne le problème en lui faisant sauter le processus de notation. L'indice de signature est une bonne solution de contournement.

Pour ce problème, j'ai examiné de plus près le code et j'ai découvert qu'il y avait en fait un bogue qui faisait échouer cela. Et heureusement, c'est une solution facile. Je ferai un PR avec un test unitaire dans un instant.

avez-vous essayé d'utiliser un indice de signature de constructeur ?

Voir

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

à titre d'exemple.

J'ai essayé d'ajouter une signature comme indiqué par le code ci-dessous tout à l'heure, mais elle a émis une erreur d'assertion. Où ai-je foiré ?

Erreur

  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

Code Python avec 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()

Voici le code correspondant :

            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

Pourquoi les indices de signature ne peuvent-ils pas être utilisés avec des arguments variables ?

Peu importe, j'ai compris et j'ai une solution à cela. Je vais l'ajouter au PR.

@enjoybeta J'ai corrigé cela dans le PR, mais en fin de compte, la solution de contournement de l'indice de signature ne fonctionne pas dans la version actuelle.

@cmacdonald , existe-t-il une autre solution de contournement qu'ils peuvent utiliser ici ?

Rien de ce qui me vient à l'esprit - ajouter une classe d'usine Java rapide qui appelle le constructeur varargs ?

Quoi qu'il en soit, je propose que nous puissions clore le problème car la prochaine version de Jnius corrigera le bogue.

Bonne idée! Une méthode d'usine peut s'en occuper si la modification de ce code source est une option. Sinon, ils peuvent créer une classe d'utilitaire d'assistance distincte qui le fait pour eux.

D'accord, nous pouvons clore ce problème maintenant.

Cette page vous a été utile?
0 / 5 - 0 notes