我的目标是用JVM语言创建基于文本的应用程序,
现在我正尝试在JNI中使用ncurses。
当我直接从C使用ncurses时,终端将触发getch()
并返回410(KEY_RESIZE)。
但是我通过JNI使用ncurses,getch()
不会做任何事情,直到按下任何其他键。
- 这是JVM的局限性吗?
- 这种情况有什么变通办法吗?
- 还是我不应该首先通过JNI使用ncurses?
以下是完整的可复制代码:
public class Main {
public static native void init();
public static native int getch();
public static native void printw(String string);
public static native void endwin();
public static void main(String[] args) {
System.loadLibrary("jcurses");
init();
for (int key; (key = getch()) != 'q';)
printw("%d\n".formatted(key));
endwin();
}
}
#include <ncurses.h>
#include "Main.h"
JNIEXPORT void JNICALL Java_Main_init(JNIEnv *env, jclass clazz) {
initscr();
keypad(stdscr, TRUE);
noecho();
}
JNIEXPORT jint JNICALL Java_Main_getch(JNIEnv *env, jclass clazz) {
return (long) getch();
}
JNIEXPORT void JNICALL Java_Main_printw(JNIEnv *env, jclass clazz, jstring javaString) {
const char *nativeString = (*env)->GetStringUTFChars(env, javaString, 0);
printw("%s", nativeString);
(*env)->ReleaseStringUTFChars(env, javaString, nativeString);
}
JNIEXPORT void JNICALL Java_Main_endwin(JNIEnv *env, jclass clazz) {
endwin();
}
all:
javac -h . Main.java
gcc -I"$$JAVA_HOME/include" -I"$$JAVA_HOME/include/linux" jcurses.c -shared -o libjcurses.so -lncurses
run:
java -Djava.library.path=. Main
为了比较,这里是做同样事情的纯C代码。
调整窗口大小将立即显示410,但不能用JNI做同样的事情。
#include <ncurses.h>
int main() {
initscr();
keypad(stdscr, TRUE);
noecho();
for (int key; (key = getch()) != 'q';)
printw("%d\n", key);
endwin();
return 0;
}
型
在以下设备上测试:
- x86 ubuntu22.04,ssh来自Windows 7 git bash
- arm64 ubuntu22.04,原生gnome终端
1条答案
按热度按时间taor4pac1#
我发现问题在于JVM“消耗”了SIGWINCH信号,
因此nCurses不能检测到窗口大小的变化。
因此,一种可能的解决方案是使用
sun.misc.Signal
类来捕获信号并进行渲染,但这是一个绝对坏主意,因为它已过时。
字符串
(This答案不应被接受)