Pyjnius: Gagal menemukan konstruktor ketika ada banyak konstruktor (kelebihan beban)

Dibuat pada 22 Okt 2020  ·  8Komentar  ·  Sumber: kivy/pyjnius

Menemukan bug dengan pyjnius ketika berhadapan dengan kelas Java dengan banyak konstruktor.

Ketika saya mengeksekusi kode Java di bawah ini, metode utama akan memanggil konstruktor ke-2 dan selesai dengan anggun.
Ketika saya mengeksekusi kode python di bawah ini, itu akan melaporkan bahwa konstruktor tidak ditemukan.
(jnius.JavaException: No constructor matching your arguments, available: ['(ILjava/lang/String;)V', '(ILjava/lang/String;Ljava/lang/Object;[I)V'])
Tetapi ketika saya menghapus konstruktor pertama dalam kode Java, kode python saya dengan pyjnius dapat dengan benar menemukan satu-satunya konstruktor dan menyelesaikan dengan anggun.

Kelas Jawa

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

Kode python dengan 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()

Komentar yang paling membantu

Ketika pyjnius memanggil metode atau konstruktor, pertama-tama ia memeriksa apakah ada 0, 1, atau beberapa konstruktor atau metode dengan nama yang diberikan. Jika hanya ada 1 itu selalu membuat panggilan, berharap yang terbaik. Jika ada beberapa, proses penilaian ini dilakukan untuk mencoba memutuskan apakah masing-masing dapat diterima atau tidak. Mudah-mudahan satu dan hanya satu yang bisa diterima; jika tidak, itu melempar kesalahan.

Dalam hal ini, menolak keduanya karena konstruktor tidak dapat diterima. Menggunakan petunjuk tanda tangan mengatasi masalah dengan membuatnya melewati proses penilaian. Petunjuk tanda tangan adalah solusi yang baik.

Untuk masalah ini, saya melihat lebih dekat pada kode dan menemukan sebenarnya ada bug yang menyebabkan ini gagal. Dan dengan senang hati itu adalah perbaikan yang mudah. Saya akan membuat PR dengan unit test sebentar lagi.

Semua 8 komentar

sudahkah Anda mencoba menggunakan petunjuk tanda tangan konstruktor?

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

Ketika pyjnius memanggil metode atau konstruktor, pertama-tama ia memeriksa apakah ada 0, 1, atau beberapa konstruktor atau metode dengan nama yang diberikan. Jika hanya ada 1 itu selalu membuat panggilan, berharap yang terbaik. Jika ada beberapa, proses penilaian ini dilakukan untuk mencoba memutuskan apakah masing-masing dapat diterima atau tidak. Mudah-mudahan satu dan hanya satu yang bisa diterima; jika tidak, itu melempar kesalahan.

Dalam hal ini, menolak keduanya karena konstruktor tidak dapat diterima. Menggunakan petunjuk tanda tangan mengatasi masalah dengan membuatnya melewati proses penilaian. Petunjuk tanda tangan adalah solusi yang baik.

Untuk masalah ini, saya melihat lebih dekat pada kode dan menemukan sebenarnya ada bug yang menyebabkan ini gagal. Dan dengan senang hati itu adalah perbaikan yang mudah. Saya akan membuat PR dengan unit test sebentar lagi.

sudahkah Anda mencoba menggunakan petunjuk tanda tangan konstruktor?

Lihat

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

untuk contoh.

Saya mencoba menambahkan tanda tangan seperti yang ditunjukkan oleh kode di bawah ini sekarang, tetapi itu mengeluarkan Kesalahan Pernyataan. Di mana saya mengacaukan?

Kesalahan

  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

Kode python dengan 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()

Berikut adalah kode yang relevan:

            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

Mengapa petunjuk tanda tangan tidak dapat digunakan dengan argumen variabel?

Tidak apa-apa, saya menemukan jawabannya dan memiliki perbaikan untuk ini. Saya akan menambahkannya ke PR.

@enjoybeta Saya memperbaiki ini di PR, tetapi intinya, solusi petunjuk tanda tangan tidak berfungsi di rilis saat ini.

@cmacdonald , apakah ada solusi lain yang dapat mereka gunakan di sini?

Tidak ada yang di atas kepala saya - tambahkan kelas pabrik Java cepat yang memanggil konstruktor varargs?

Bagaimanapun, saya mengusulkan kita dapat menutup masalah karena rilis Jnius berikutnya akan memperbaiki bug.

Ide bagus! Metode pabrik dapat menanganinya jika mengubah kode sumber itu adalah opsi. Jika tidak, mereka dapat membuat kelas utilitas pembantu terpisah yang melakukannya untuk mereka.

Setuju, kita bisa menutup masalah ini sekarang.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat