Pyjnius: Falha ao encontrar o construtor quando há vários construtores (sobrecarregados)

Criado em 22 out. 2020  ·  8Comentários  ·  Fonte: kivy/pyjnius

Encontrado um bug com pyjnius ao lidar com uma classe Java com vários construtores.

Quando eu executei o código Java abaixo, o método principal invocará o segundo construtor e terminará normalmente.
Quando eu executar o código Python abaixo, ele relatará que o construtor não foi encontrado.
(jnius.JavaException: No constructor matching your arguments, available: ['(ILjava/lang/String;)V', '(ILjava/lang/String;Ljava/lang/Object;[I)V'])
Mas quando removi o primeiro construtor no código java, meu código python com pyjnius pode encontrar corretamente o único construtor e terminar com perfeição.

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

Código Python com 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()

Comentários muito úteis

Quando pyjnius chama um método ou construtor, ele primeiro verifica se há 0, 1 ou vários construtores ou métodos com o nome fornecido. Se houver apenas 1, ele sempre fará a decisão, esperando o melhor. Se houver vários, ele faz esse processo de pontuação para tentar decidir se cada um é aceitável ou não. Esperançosamente, um e apenas um é aceitável; caso contrário, ele gera um erro.

Nesse caso, ele está rejeitando ambos, pois os construtores são inaceitáveis. Usar uma dica de assinatura contorna o problema, fazendo com que ela ignore o processo de pontuação. A dica de assinatura é uma boa solução alternativa.

Para esse problema, examinei o código mais de perto e descobri que, na verdade, há um bug que está causando a falha dele. E felizmente é uma solução fácil. Vou fazer um PR com um teste de unidade em um momento.

Todos 8 comentários

você tentou usar uma dica de assinatura do construtor?

Consulte https://github.com/kivy/pyjnius/blob/307659b13c1e5583fcb25603b7d3732265ffd4a0/tests/test_constructor.py#L54 para obter um exemplo.

Quando pyjnius chama um método ou construtor, ele primeiro verifica se há 0, 1 ou vários construtores ou métodos com o nome fornecido. Se houver apenas 1, ele sempre fará a decisão, esperando o melhor. Se houver vários, ele faz esse processo de pontuação para tentar decidir se cada um é aceitável ou não. Esperançosamente, um e apenas um é aceitável; caso contrário, ele gera um erro.

Nesse caso, ele está rejeitando ambos, pois os construtores são inaceitáveis. Usar uma dica de assinatura contorna o problema, fazendo com que ela ignore o processo de pontuação. A dica de assinatura é uma boa solução alternativa.

Para esse problema, examinei o código mais de perto e descobri que, na verdade, há um bug que está causando a falha dele. E felizmente é uma solução fácil. Vou fazer um PR com um teste de unidade em um momento.

você tentou usar uma dica de assinatura do construtor?

Ver

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

Por exemplo.

Tentei adicionar uma assinatura conforme mostrado pelo código abaixo agora, mas emitiu um erro de declaração. Onde eu errei?

Erro

  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

Código Python com 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()

Aqui está o código relevante:

            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

Por que as dicas de assinatura não podem ser usadas com argumentos variáveis?

Não importa, eu descobri e tenho uma solução para isso. Vou adicioná-lo ao PR.

@enjoybeta Corrigi isso no PR, mas no final das

@cmacdonald , há outra solução alternativa que eles possam usar aqui?

Nada do topo da minha cabeça - adicionar uma classe de fábrica Java rápida que chama o construtor varargs?

De qualquer forma, proponho que possamos resolver o problema, pois a próxima versão do Jnius corrigirá o bug.

Boa ideia! Um método de fábrica pode cuidar disso se alterar o código-fonte for uma opção. Caso contrário, eles podem criar uma classe de utilitário auxiliar separada que faça isso por eles.

Concordo, podemos encerrar esse problema agora.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

Hukuta picture Hukuta  ·  5Comentários

apalala picture apalala  ·  7Comentários

cmacdonald picture cmacdonald  ·  20Comentários

ignertic picture ignertic  ·  4Comentários

ghost picture ghost  ·  3Comentários