Having successfully implemented the FFI to be able to parse XML docs, I am now trying to redirect libxml's stderr output into my own log function inside my Rust application (wrapping the log crate macros) so that I can keep any errors together with the rest of the debug logging.
According to the libxml docs, I need to use initGenericErrorDefaultFunc (xmlGenericErrorFunc * handler) to specify the handler for errors, which I think takes a pointer to my Rust function, but I am unsure how to pass my Rust function to C via the FFI. Using the first edition of The Book, I ended up with:
pub enum XmlGenericErrorFunc {}
#[link(name = "xml2")]
extern "C" {
pub fn initGenericErrorDefaultFunc(handler: XmlGenericErrorFunc);
pub fn xmlGenericErrorFunc(
ctx: *mut XmlValidCtxtPtr,
msg: *const c_char,
) -> XmlGenericErrorFunc;
}
#[no_mangle]
extern fn error_func_redirect(msg: *const c_char) {
error!("libxml error output: {:?}", msg);
}
As soon as I've setup my context, I'm then trying to tell libxml about my Rust function (which I thought I had to pass the function signature in via):
let cvp_ptr: *mut XmlValidCtxtPtr = create_context_ptr()?;
unsafe {
let error_function_name = std::ffi::CString::new("error_func_redirect(msg: *const c_char)").unwrap();
let error_func = xmlGenericErrorFunc(cvp_ptr, error_function_name.as_ptr());
initGenericErrorDefaultFunc(error_func);
}
But I get a linker error:
Undefined symbols for architecture x86_64:
"_xmlGenericErrorFunc", referenced from:
validator::XmlValidator::new::h3155275e1d619a12 in libvalidator-206fd62ca886041b.rlib(validator-206fd62ca886041b.4pmkvih2bq1byoha.rcgu.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I'm now in a tangle trying to work out how I correctly pass a pointer to my Rust function through into libxml. Any tips most appreciated!