KWARC / rust-libxml

Rust wrapper for libxml2
https://crates.io/crates/libxml
MIT License
76 stars 38 forks source link

Declare function to xmllib2 using rust-libxml #132

Closed hurricane-socrates closed 5 months ago

hurricane-socrates commented 6 months ago

This is a question also asked on rust-users

I'm working on an scxml interpreter. I want to declare a function to the xml path context. I'd appreciate some guidance.

It looks like I'll need this function signature:

unsafe extern "C" fn(ctxt: xmlXPathParserContextPtr, nargs: ::std::os::raw::c_int)

I'd like this function to be written in Rust. However, it looks like a function signature for that is

unsafe extern "C" fn(ctxt: xmlXPathParserContextPtr, nargs: ::std::os::raw::c_int) {}

I'm trying to use this as follows:

let funcname = CString::new("In").unwrap();
let func = Some(in_func);
let rslt = unsafe {
     xmlXPathRegisterFunc(context.as_ptr(), funcname.as_ptr() as *const u8, func)
};

which gives this error:


error[E0308]: mismatched types
      |
277   |                 xmlXPathRegisterFunc(context.as_ptr(), funcname.as_ptr() as *const u8, func)
      |                 -------------------- arguments to this function are incorrect          ^^^^ expected `Option<unsafe extern "C" fn(..., ...)>`, found `Option<unsafe extern "C" fn(..., ...) {in_func}>`
      |
      = note: expected enum `Option<unsafe extern "C" fn(_, _)>`
                 found enum `Option<unsafe extern "C" fn(_, _) {in_func}>`
note: function defined here
     --> libxml-0.3.3/src/bindings.rs:20561:10
      |
20561 |   pub fn xmlXPathRegisterFunc(
      |          ^^^^^^^^^^^^^^^^^^^^
hurricane-socrates commented 6 months ago

Thanks for the update. Somehow I didn't get notified of the label addtions. I've moved on from this problem as being unsolvable given my level of Rust knowledge, though I do appreciate the "help wanted" label.

anwaralameddin commented 6 months ago

You could explicitly cast the function item as a function pointer:

let in_func = in_func as unsafe extern "C" fn(ctxt: xmlXPathParserContextPtr, nargs: ::std::os::raw::c_int);
let func = Some(in_func);

Or use type coercion instead:

let func: xmlXPathFunction = Some(in_func);

A minimal example following the OP would be:

#[test]
fn test_rust_xml_xpath_register_func(){
    extern "C" fn in_func(ctxt: xmlXPathParserContextPtr, nargs: ::std::os::raw::c_int) {}
    let context_ptr = std::ptr::null_mut();
    let funcname = std::ffi::CString::new("In").unwrap();
    // let in_func = in_func as unsafe extern "C" fn(ctxt: xmlXPathParserContextPtr, nargs: ::std::os::raw::c_int);
    // let func = Some(in_func);
    let func: xmlXPathFunction = Some(in_func);
    let rslt = unsafe {
        xmlXPathRegisterFunc(context_ptr, funcname.as_ptr() as *const u8, func)
    };
}
hurricane-socrates commented 6 months ago

Thanks! I willl take a look at that technique.