簡體   English   中英

Java/Rust 日志橋

[英]Java/Rust logging bridge

我有一個 Java 程序,它使用 JNI 調用 Rust 庫。 在 rust 代碼中,我有電話咨詢info! 沒有出現在 output 中。 我 99% 肯定這是因為我沒有初始化 Rust 日志系統。

When I had a similar problem in Python code calling Rust code, there was a module that I added which did the work to connect the Rust logging system to the python logger.

Rust 和 Java 是否有類似的橋接?

我在 Java 中使用slf4j ,在 Rust 中使用log::info

我搜索了一座橋,但我找到的最接近的是如何從 Java 調用 Rust。

log庫僅提供一種將日志消息傳遞到全局掛鈎的機制。 必須使用 function 調用log::set_logger()來處理消息。 多種庫可以用於此目的 如果您想將log記錄連接到slf4j ,您將需要查找或編寫專門執行該組合的代碼。 (我對 JNI+Rust 知之甚少,所以我不能說是否已經存在。)

  1. 創建自己的記錄器(不要使用 env_logger 或其他):
use std::sync::Arc;
use log::{LevelFilter, Level};
pub type LogCallbackType = Arc<dyn Fn(Level, String) + Send + Sync>;
pub struct SimpleLogger {
  callback: LogCallbackType,
  level: LevelFilter,
}
  1. 提供 function 以將回調綁定到您的記錄器
impl SimpleLogger {
  pub fn init(level: LevelFilter, callback: LogCallbackType) {
    let message = std::format!("Initialize logging to {}", &level);
    callback(Level::Debug, message);

    log::set_boxed_logger(Box::new(SimpleLogger { callback, level }))
      .map(|()| log::set_max_level(level));
  }
  1. 將您的 function 外化為其他語言
use std::os::raw::c_char;
pub type NativeString = *const c_char;
pub type ExternLogCallbackType = Option<extern "C" fn(u32, NativeString)>;

#[no_mangle]
pub extern fn init_logging(level: u32, callback: ExternLogCallbackType) {
  if !callback.is_none() {
    let callback = callback.unwrap();
    let level_filter = SimpleLogger::u32_to_level_filter(level);
    SimpleLogger::init(level_filter, Arc::new(move |level, msg| {
      callback(level as u32, msg.as_ptr());
    }))
  }
}
  1. 准備 JNA 的東西
public static class LogCallback implements Callback {
  public static final Logger LOGGER = LoggerFactory.getLogger("myrustliblog");

  public void callback(int level, String message) {
    switch (level) {
      case 0:
        break;
      case 1:
        LOGGER.error(message);
        break;
      case 2:
        LOGGER.warn(message);
        break;
      case 3:
        LOGGER.info(message);
        break;
      case 4:
        LOGGER.debug(message);
        break;
      case 5:
        LOGGER.trace(message);
        break;
      default:
        LOGGER.trace(message);
        break;
    }
  }
}

public interface MyNativeInterface extends Library {
   //...other stuff ...

   String init_logging(int level, LogCallback callback);
   //...
}
  1. 最后從 Java 初始化日志記錄:
static final LogCallback LOG_CALLBACK = new LogCallback();

public static void initLogging(org.slf4j.event.Level level) {
    int iLevel = 0;
    switch (level) {
      case ERROR:
        iLevel = 1;
        break;
      case WARN:
        iLevel = 2;
        break;
      case INFO:
        iLevel = 3;
        break;
      case DEBUG:
        iLevel = 4;
        break;
      case TRACE:
        iLevel = 5;
        break;
    }
    _myInterfaceJnaInstance.init_logging(iLevel, LOG_CALLBACK);
  }

筆記:

  1. 我省略了 Rust 中的結果處理。 你應該能夠做到
  2. 這是來自我的運行代碼,它有效。 但是您可能需要對 memory 泄漏進行一些調整(即在記錄后釋放字符串)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM