Re: [rust-dev] Calling back into Rust from C code
On Sun, May 12, 2013 at 3:23 AM, Florian Weimer wrote: > * Skirmantas Kligys: > >> I am trying to write a native wrapper for >> >> https://github.com/pascalj/rust-expat >> >> (BTW, if there is a native Rust XML parser, I am interested to hear >> about it, did not find it). I have trouble calling back into Rust >> from C code: > > It's probably better to avoid calling back into Rust, storing events > in a buffer in C callbacks. Florian, Any reasons why? Stack overflows? I now have two working approaches: 1. Store Rust callbacks in a struct, pass it through expat as user_data: *c_void, cast it back into a struct in a C callback, call the Rust callback. 2. Create a port/chan pair, pass the chan through expat as user_data: *c_void, cast it back into chan in a C callback, use it to send XmlEvent enum variants; a child task listens on the port and does the processing. The second approach seems more "rusty" and probably will load two cores unlike the first. Both approaches pass data around as *c_void, which makes me a bit nervous, but I just don't see any other way to pass typed pointers into a C callback. Let me know if I am missing something. Thanks. Skirmantas Kligys ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Calling back into Rust from C code
On 05/10/2013 06:04 PM, Skirmantas Kligys wrote: I am trying to write a native wrapper for https://github.com/pascalj/rust-expat (BTW, if there is a native Rust XML parser, I am interested to hear about it, did not find it). I have trouble calling back into Rust from C code: fn set_element_handlers(parser: expat::XML_Parser, start_handler: &fn(tag: &str, attrs: &[@str]), end_handler: &fn(tag: &str)) { let start_cb = |_user_data: *c_void, c_name: *c_char, _c_attrs: **c_char| { unsafe { let name = str::raw::from_c_str(c_name); start_handler(name, []); } }; let end_cb = |_user_data: *c_void, c_name: *c_char| { unsafe { let name = str::raw::from_c_str(c_name); end_handler(name); } }; expat::XML_SetElementHandler(parser, start_cb, end_cb); } This says that it saw &fn... instead of expected extern fn for the second and third parameter. Any ideas how to do this? You need a function type that is compatible with C. Here `start_cb` is a Rust closure, using the Rust ABI, but you need it to be a C function pointer. It should be defined more like extern fn start_cb(user_data: *c_void, c_name: *c_char, c_attrs: **c_char) { ... } The `extern` says that it uses a foreign ABI, C by default. You can take a value to it like let start: *u8 = start_cb; Note that the extern fn has type *u8. This is a temporary hack. Eventually it will have type `extern "C" fn(...)`. Then your XML_SetElementHandler can be defined like `fn XML_SetELementHandler(parser: Parser, start_cb: *u8, end_cb: *u8)`. Good luck. -Brian ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Calling back into Rust from C code
* Skirmantas Kligys: > I am trying to write a native wrapper for > > https://github.com/pascalj/rust-expat > > (BTW, if there is a native Rust XML parser, I am interested to hear > about it, did not find it). I have trouble calling back into Rust > from C code: It's probably better to avoid calling back into Rust, storing events in a buffer in C callbacks. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Calling back into Rust from C code
As the error implies, the function type that you try to pass as a callback is incorrect. The problem is that because the callback is called from C it ought to be "compatible" with C, thus the "extern" bit. Rather than defining an anonymous function, you need to write an "extern fn" function (with a name), so that the function (at low-level) have a compatible ABI with C. -- Matthieu On Sat, May 11, 2013 at 3:04 AM, Skirmantas Kligys < skirmantas.kli...@gmail.com> wrote: > I am trying to write a native wrapper for > > https://github.com/pascalj/rust-expat > > (BTW, if there is a native Rust XML parser, I am interested to hear > about it, did not find it). I have trouble calling back into Rust > from C code: > > fn set_element_handlers(parser: expat::XML_Parser, start_handler: > &fn(tag: &str, attrs: &[@str]), end_handler: &fn(tag: &str)) { > let start_cb = |_user_data: *c_void, c_name: *c_char, _c_attrs: > **c_char| { > unsafe { > let name = str::raw::from_c_str(c_name); > start_handler(name, []); > } > }; > > let end_cb = |_user_data: *c_void, c_name: *c_char| { > unsafe { > let name = str::raw::from_c_str(c_name); > end_handler(name); > } > }; > > expat::XML_SetElementHandler(parser, start_cb, end_cb); > } > > This says that it saw &fn... instead of expected extern fn for the > second and third parameter. Any ideas how to do this? > > Thanks. > ___ > Rust-dev mailing list > Rust-dev@mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] Calling back into Rust from C code
I am trying to write a native wrapper for https://github.com/pascalj/rust-expat (BTW, if there is a native Rust XML parser, I am interested to hear about it, did not find it). I have trouble calling back into Rust from C code: fn set_element_handlers(parser: expat::XML_Parser, start_handler: &fn(tag: &str, attrs: &[@str]), end_handler: &fn(tag: &str)) { let start_cb = |_user_data: *c_void, c_name: *c_char, _c_attrs: **c_char| { unsafe { let name = str::raw::from_c_str(c_name); start_handler(name, []); } }; let end_cb = |_user_data: *c_void, c_name: *c_char| { unsafe { let name = str::raw::from_c_str(c_name); end_handler(name); } }; expat::XML_SetElementHandler(parser, start_cb, end_cb); } This says that it saw &fn... instead of expected extern fn for the second and third parameter. Any ideas how to do this? Thanks. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev