feat(android-ffi): nativeLastErrorKind 出口带错误分类(3a)
LAST_ERROR 槽位改存 (kind, detail),新增 nativeLastErrorKind();FFI 契约 kind 先取、message 后取(消息读走清空槽位)。kind 编号与 viewer_core:: ConnectErrorKind::code 一致,跨 FFI 只传整数。JNI 符号 12→13 全部导出(字节扫描核)。
This commit is contained in:
parent
4eb82f9779
commit
f28db050fb
@ -34,7 +34,8 @@ struct SessionBox {
|
|||||||
runtime: tokio::runtime::Runtime,
|
runtime: tokio::runtime::Runtime,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 连接被控端。成功返回句柄(>0),失败返回 0;错误消息经 `nativeLastError()` 取。
|
/// 连接被控端。成功返回句柄(>0),失败返回 0;错误消息经 `nativeLastError()` 取,
|
||||||
|
/// **错误分类**经 `nativeLastErrorKind()` 取(3a:界面按分类显示中文文案,原始英文作第二行)。
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "system" fn Java_com_verify_remote_RustBridge_nativeConnect<'local>(
|
pub extern "system" fn Java_com_verify_remote_RustBridge_nativeConnect<'local>(
|
||||||
mut env: JNIEnv<'local>,
|
mut env: JNIEnv<'local>,
|
||||||
@ -46,14 +47,14 @@ pub extern "system" fn Java_com_verify_remote_RustBridge_nativeConnect<'local>(
|
|||||||
let host_s = match env.get_string(&host) {
|
let host_s = match env.get_string(&host) {
|
||||||
Ok(s) => s.to_string_lossy().into_owned(),
|
Ok(s) => s.to_string_lossy().into_owned(),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
set_last_error("host 参数不是合法字符串");
|
set_last_error(-1, "host 参数不是合法字符串");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let code_s = match env.get_string(&code) {
|
let code_s = match env.get_string(&code) {
|
||||||
Ok(s) => s.to_string_lossy().into_owned(),
|
Ok(s) => s.to_string_lossy().into_owned(),
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
set_last_error("code 参数不是合法字符串");
|
set_last_error(-1, "code 参数不是合法字符串");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -64,7 +65,7 @@ pub extern "system" fn Java_com_verify_remote_RustBridge_nativeConnect<'local>(
|
|||||||
.build()
|
.build()
|
||||||
{
|
{
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(e) => return Err(format!("runtime init: {e}")),
|
Err(e) => return Err((-1i32, format!("runtime init: {e}"))),
|
||||||
};
|
};
|
||||||
let cfg = ConnectConfig::direct(host_s, port as u16, code_s);
|
let cfg = ConnectConfig::direct(host_s, port as u16, code_s);
|
||||||
match runtime.block_on(Session::connect(cfg)) {
|
match runtime.block_on(Session::connect(cfg)) {
|
||||||
@ -72,53 +73,73 @@ pub extern "system" fn Java_com_verify_remote_RustBridge_nativeConnect<'local>(
|
|||||||
session: Arc::new(session),
|
session: Arc::new(session),
|
||||||
runtime,
|
runtime,
|
||||||
}),
|
}),
|
||||||
Err(e) => Err(format!("{e:#}")),
|
// ConnectError 的 Display 即原始 detail;kind.code() 与
|
||||||
|
// viewer_core::ConnectErrorKind::code 的映射表一致(FFI 契约)。
|
||||||
|
Err(e) => Err((e.kind.code(), e.detail)),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
match built {
|
match built {
|
||||||
Ok(Ok(boxed)) => {
|
Ok(Ok(boxed)) => {
|
||||||
set_last_error("");
|
set_last_error(0, "");
|
||||||
Box::into_raw(Box::new(Mutex::new(boxed))) as jlong
|
Box::into_raw(Box::new(Mutex::new(boxed))) as jlong
|
||||||
}
|
}
|
||||||
Ok(Err(msg)) => {
|
Ok(Err((kind, msg))) => {
|
||||||
set_last_error(&msg);
|
set_last_error(kind, &msg);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
set_last_error("panic in nativeConnect");
|
set_last_error(-1, "panic in nativeConnect");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_last_error(msg: &str) {
|
/// kind = 0 表示清除;-1 表示 FFI 层自身错误(无 viewer-core 分类,Kotlin 走 Other 文案)。
|
||||||
|
fn set_last_error(kind: i32, msg: &str) {
|
||||||
let mut slot = LAST_ERROR.lock().unwrap();
|
let mut slot = LAST_ERROR.lock().unwrap();
|
||||||
if msg.is_empty() {
|
if msg.is_empty() {
|
||||||
*slot = None;
|
*slot = None;
|
||||||
} else {
|
} else {
|
||||||
*slot = Some(msg.to_string());
|
*slot = Some((kind, msg.to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static LAST_ERROR: Mutex<Option<String>> = Mutex::new(None);
|
static LAST_ERROR: Mutex<Option<(i32, String)>> = Mutex::new(None);
|
||||||
|
|
||||||
/// 取最近一次 nativeConnect 的错误消息(无错误返回 null)。
|
/// 取最近一次 nativeConnect 的错误消息(无错误返回 null)。
|
||||||
|
/// FFI 契约:调用方必须先 `nativeLastErrorKind()` 再 `nativeLastError()`——
|
||||||
|
/// 本函数读走消息时**清空整个槽位**(kind 一起失效),颠倒顺序会拿到 kind=0。
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "system" fn Java_com_verify_remote_RustBridge_nativeLastError<'local>(
|
pub extern "system" fn Java_com_verify_remote_RustBridge_nativeLastError<'local>(
|
||||||
env: JNIEnv<'local>,
|
env: JNIEnv<'local>,
|
||||||
_class: JClass<'local>,
|
_class: JClass<'local>,
|
||||||
) -> jstring {
|
) -> jstring {
|
||||||
let msg = LAST_ERROR.lock().unwrap().take();
|
let mut slot = LAST_ERROR.lock().unwrap();
|
||||||
|
let msg = slot.as_ref().map(|(_, m)| m.clone());
|
||||||
match msg {
|
match msg {
|
||||||
Some(m) => env
|
Some(m) => {
|
||||||
.new_string(m)
|
*slot = None;
|
||||||
|
env.new_string(m)
|
||||||
.map(|s| s.into_raw())
|
.map(|s| s.into_raw())
|
||||||
.unwrap_or(std::ptr::null_mut()),
|
.unwrap_or(std::ptr::null_mut())
|
||||||
|
}
|
||||||
None => std::ptr::null_mut(),
|
None => std::ptr::null_mut(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 取最近一次 nativeConnect 的错误分类码(viewer_core::ConnectErrorKind::code)。
|
||||||
|
/// 只读不清空;0 = 无错误,-1 = FFI 层自身错误(参数非法/panic/runtime 初始化失败,
|
||||||
|
/// 无 viewer-core 分类,Kotlin 按 Other 文案 + 原始消息显示)。
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "system" fn Java_com_verify_remote_RustBridge_nativeLastErrorKind(
|
||||||
|
_env: JNIEnv,
|
||||||
|
_class: JClass,
|
||||||
|
) -> jint {
|
||||||
|
let slot = LAST_ERROR.lock().unwrap();
|
||||||
|
slot.as_ref().map(|(k, _)| *k).unwrap_or(0)
|
||||||
|
}
|
||||||
|
|
||||||
/// 取下一帧(阻塞直到有帧或会话结束)。返回 null = 会话结束。
|
/// 取下一帧(阻塞直到有帧或会话结束)。返回 null = 会话结束。
|
||||||
/// 仅允许解码线程调用;destroy 前必须先停止本线程(见文件头锁纪律)。
|
/// 仅允许解码线程调用;destroy 前必须先停止本线程(见文件头锁纪律)。
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user