最近,我一直在开发一个使用 GTK4 的小型 GUI 应用程序。这个 gui 应用程序使用 Java 和 Rust 的组合(我使用 jni crate 进行互操作)。
我正在使用 Rust 中的 Gtk-rs 箱创建 Gui 窗口。我有使用 JNI 调用 Rust 的 Java 代码。
编译过程非常顺利,我从 Rust 端生成一个动态库 (.so) 并将其加载到 Java 中,编译 Java 文件并创建可执行的 Java 存档。本机库是动态链接的。
但是,当我执行存档时,我收到了这个奇怪的消息:
“未知选项-jar”
什么也没有发生。
Java中的main函数定义为:
//runner.java
public static void main(String[] args) {
Application app = new Application(
"Test",
"/home/radon/RustroverProjects/guiframe/target/release/libguiframe.so"
);
}
此应用程序类将应用程序名称和库路径作为其构造函数参数。
Application 构造函数定义为(只有 1 个构造函数):
public Application(
String name,
String nativeLibAbsolutePath
) {
this.name = name;
bridge = new NativeBridge(nativeLibAbsolutePath); //bridge is a class field
bridge.getApplication(this);
}
NativeBridge 类的 getApplication 函数是在 Rust 中定义的。它使用 JNI 访问类的名称字段,并使用 start 函数(使用 get_app 函数)创建一个 GTK 窗口:
//This is the getApplication method.
#[allow(static_mut_refs)]
#[allow(non_snake_case)]
#[no_mangle]
pub(crate) extern "C" fn Java_ix_radon_guiframe_ffi_NativeBridge_getApplication<'local> (
mut env: JNIEnv<'local>,
_native_bridge_object: JObject<'local>,
app: JObject
) {
let _name = Into::<JString>::into(env.get_field(&app, "name", "Ljava/lang/String;").unwrap().l().unwrap());
let name = Into::<String>::into(env.get_string(&_name).unwrap());
unsafe {
JAPPLICATION = Application { //JAPPLICATION is a mutable static
name
};
JAPPLICATION.start();
}
}
#[allow(static_mut_refs)]
pub(crate) fn get_app(name: String) {
let app = Application::builder()
.application_id(&format!("ix.radon.guiframe.{}", &name))
.build();
app.connect_activate(move |app| {
let window = ApplicationWindow::builder()
.application(app)
.default_width(960)
.default_height(540)
.title(&name)
.build();
window.present();
});
app.run();
}
我已经检查了 jar 的清单和其他所有内容,但它似乎不起作用。
如果我不在主函数中使用 Application 类,一切都会正常工作。
我确实添加了
.flags(ApplicationFlags::HANDLES_COMMAND_LINE)
并进行了测试。幸运的是,Unknown option -jar 不会发生,但我在执行 jar 时得到了这个:
(java:17014): Gtk-警告 **: /my_path/.config/gtk-4.0/settings.ini
中未知的关键 gtk 模块(java:17014): GLib-GIO-WARNING **: 您的应用程序声称支持自定义命令行处理,但没有实现 g_application_command_line() 并且没有连接到“命令行”信号的处理程序。
对此提供一些帮助会很好。
这实际上是GApplication
GtkApplication
的超类)的默认行为:
GApplication 以对大多数人来说合理的方式处理参数 应用:
不带命令行参数的调用会导致应用程序被激活(即:发出“激活”信号或 您的“激活”方法被调用) 在命令行上调用一个或多个文件名或 URI 将导致发出“open”信号(或“open”方法) 被叫)
如果 --gapplication-service 作为唯一的命令行参数给出,GApplication 将设置 G_APPLICATION_IS_SERVICE 标志并 在服务模式下运行。请参阅 HowDoI/DBusApplicationLaunching 相关信息。
如果应用程序启用它,--gapplication-app-id可用于覆盖应用程序id
如果使用 GtkApplication 那么 Gtk 特定的命令行参数将以通常的方式处理
--支持帮助
所有其他命令行标志都被拒绝
您可以通过告诉 Gtk(Glib,真的)您的应用程序将进行自己的处理来禁用此默认处理:
let app = Application::builder()
.application_id(&format!("ix.radon.guiframe.{}", &name))
.flags(ApplicationFlags::HANDLES_COMMAND_LINE) // <-- add this line
.build();