複数のコンストラクターを持つJavaクラスを処理するときに、pyjniusのバグが見つかりました。
以下のJavaコードを実行すると、mainメソッドは2番目のコンストラクターを呼び出し、正常に終了します。
以下のPythonコードを実行すると、コンストラクターが見つからないことが報告されます。
(jnius.JavaException: No constructor matching your arguments, available: ['(ILjava/lang/String;)V', '(ILjava/lang/String;Ljava/lang/Object;[I)V'])
しかし、Javaコードの最初のコンストラクターを削除すると、pyjniusを使用したPythonコードは、唯一のコンストラクターを正しく見つけて、正常に終了することができます。
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);
}
}
pyjniusを使用したPythonコード
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()
コンストラクターの署名ヒントを使用してみましたか?
例については、 https://github.com/kivy/pyjnius/blob/307659b13c1e5583fcb25603b7d3732265ffd4a0/tests/test_constructor.py#L54を参照して
pyjniusがメソッドまたはコンストラクターを呼び出すと、最初に、指定された名前のコンストラクターまたはメソッドが0、1、または複数あるかどうかがチェックされます。 1つしかない場合は、常に電話をかけ、最善を期待します。 複数ある場合は、このスコアリングプロセスを実行して、それぞれが許容できるかどうかを判断しようとします。 うまくいけば、1つだけが受け入れられます。 そうでない場合は、エラーがスローされます。
この場合、コンストラクターは受け入れられないため、両方を拒否しています。 署名ヒントを使用すると、スコアリングプロセスの実行をスキップすることで、問題を回避できます。 署名のヒントは良い回避策です。
この問題については、コードを詳しく調べたところ、実際にはこれが失敗する原因となっているバグがあることがわかりました。 そして幸いなことに、それは簡単な修正です。 すぐに単体テストでPRをします。
コンストラクターの署名ヒントを使用してみましたか?
見る
例として。
以下のコードに示すように署名を追加しようとしましたが、アサーションエラーが発生しました。 どこでめちゃくちゃになりましたか?
エラー
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
pyjniusを使用したPythonコード
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()
関連するコードは次のとおりです。
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
署名ヒントを可変引数で使用できないのはなぜですか?
気にしないでください、私はそれを理解し、これを修正しました。 PRに追加します。
@enjoybetaこれをPRで修正しましたが、
@cmacdonald 、ここで使用できる別の回避策はありますか?
頭のてっぺんには何もありません-varargsコンストラクターを呼び出す簡単なJavaファクトリクラスを追加しますか?
とにかく、次のJniusリリースでバグが修正されるので、問題を解決できることを提案します。
良いアイデア! そのソースコードを変更することがオプションである場合、ファクトリメソッドがそれを処理できます。 そうでない場合は、別のヘルパーユーティリティクラスを作成して、それを実行できます。
同意しました。今すぐこの問題を解決できます。
最も参考になるコメント
pyjniusがメソッドまたはコンストラクターを呼び出すと、最初に、指定された名前のコンストラクターまたはメソッドが0、1、または複数あるかどうかがチェックされます。 1つしかない場合は、常に電話をかけ、最善を期待します。 複数ある場合は、このスコアリングプロセスを実行して、それぞれが許容できるかどうかを判断しようとします。 うまくいけば、1つだけが受け入れられます。 そうでない場合は、エラーがスローされます。
この場合、コンストラクターは受け入れられないため、両方を拒否しています。 署名ヒントを使用すると、スコアリングプロセスの実行をスキップすることで、問題を回避できます。 署名のヒントは良い回避策です。
この問題については、コードを詳しく調べたところ、実際にはこれが失敗する原因となっているバグがあることがわかりました。 そして幸いなことに、それは簡単な修正です。 すぐに単体テストでPRをします。