I have a Java program that uses JNI to call a Rust library. In the rust code, I have calls to info!
which do not appear in the output. I am 99% positive this is because I am not initializing the Rust logging system.
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.
Is there a similar bridge for Rust and Java?
I am using slf4j
in Java and log::info
in Rust.
I searched for an bridge but the closest I found was how to call Rust from Java.
The log
library provides only a mechanism for passing log messages to a global hook. Something must call log::set_logger()
with a function that does something with the messages. There are a variety of libraries you can use for this purpose ; if you want to hook up your log
logging to slf4j
you will need to find or write code that does that combination specifically. (I don't know much of anything about JNI+Rust so I can't say whether one exists already.)
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,
}
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));
}
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());
}))
}
}
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);
//...
}
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);
}
Notes:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.