Pyjnius: 有多个(重载)构造函数时找不到构造函数

创建于 2020-10-22  ·  8评论  ·  资料来源: kivy/pyjnius

在处理具有多个构造函数的 Java 类时发现 pyjnius 的错误。

当我执行下面的 Java 代码时,main 方法将调用第二个构造函数并优雅地完成。
当我执行下面的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()

最有用的评论

当 pyjnius 调用方法或构造函数时,它首先检查是否有 0、1 或多个具有给定名称的构造函数或方法。 如果只有 1,它总是会打电话,希望最好。 如果有多个,它会执行此评分过程以尝试确定每个是否可接受。 希望只有一个是可以接受的; 如果没有,它会抛出一个错误。

在这种情况下,它拒绝两者,因为构造函数是不可接受的。 使用签名提示可以通过跳过评分过程来解决问题。 签名提示是一个很好的解决方法。

对于这个问题,我仔细查看了代码,发现实际上存在导致此问题失败的错误。 很高兴这是一个简单的修复。 稍后我将通过单元测试进行 PR。

所有8条评论

您是否尝试过使用构造函数签名提示?

例如,请参见https://github.com/kivy/pyjnius/blob/307659b13c1e5583fcb25603b7d3732265ffd4a0/tests/test_constructor.py#L54

当 pyjnius 调用方法或构造函数时,它首先检查是否有 0、1 或多个具有给定名称的构造函数或方法。 如果只有 1,它总是会打电话,希望最好。 如果有多个,它会执行此评分过程以尝试确定每个是否可接受。 希望只有一个是可以接受的; 如果没有,它会抛出一个错误。

在这种情况下,它拒绝两者,因为构造函数是不可接受的。 使用签名提示可以通过跳过评分过程来解决问题。 签名提示是一个很好的解决方法。

对于这个问题,我仔细查看了代码,发现实际上存在导致此问题失败的错误。 很高兴这是一个简单的修复。 稍后我将通过单元测试进行 PR。

您是否尝试过使用构造函数签名提示?

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

举个例子。

我刚刚尝试添加一个签名,如下面的代码所示,但它发出了断言错误。 我哪里搞砸了?

错误

  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 版本将修复该错误。

好主意! 如果可以选择更改源代码,则工厂方法可以处理它。 如果没有,他们可以创建一个单独的 helper-utility 类来为他们做这件事。

同意,我们现在可以关闭这个问题。

此页面是否有帮助?
0 / 5 - 0 等级