@@ -249,6 +249,143 @@ fn main() {
249249}
250250~~~~
251251
252+ # Callbacks from C code to Rust functions
253+
254+ Some external libraries require the usage of callbacks to report back their
255+ current state or intermediate data to the caller.
256+ It is possible to pass functions defined in Rust to an external library.
257+ The requirement for this is that the callback function is marked as ` extern `
258+ with the correct calling convention to make it callable from C code.
259+
260+ The callback function that can then be sent to through a registration call
261+ to the C library and afterwards be invoked from there.
262+
263+ A basic example is:
264+
265+ Rust code:
266+ ~~~~ {.xfail-test}
267+ extern fn callback(a:i32) {
268+ println!("I'm called from C with value {0}", a);
269+ }
270+
271+ #[link(name = "extlib")]
272+ extern {
273+ fn register_callback(cb: extern "C" fn(i32)) -> i32;
274+ fn trigger_callback();
275+ }
276+
277+ fn main() {
278+ unsafe {
279+ register_callback(callback);
280+ trigger_callback(); // Triggers the callback
281+ }
282+ }
283+ ~~~~
284+
285+ C code:
286+ ~~~~ {.xfail-test}
287+ typedef void (*rust_callback)(int32_t);
288+ rust_callback cb;
289+
290+ int32_t register_callback(rust_callback callback) {
291+ cb = callback;
292+ return 1;
293+ }
294+
295+ void trigger_callback() {
296+ cb(7); // Will call callback(7) in Rust
297+ }
298+ ~~~~
299+
300+ In this example will Rust's ` main() ` will call ` do_callback() ` in C,
301+ which would call back to ` callback() ` in Rust.
302+
303+
304+ ## Targetting callbacks to Rust objects
305+
306+ The former example showed how a global function can be called from C-Code.
307+ However it is often desired that the callback is targetted to a special
308+ Rust object. This could be the object that represents the wrapper for the
309+ respective C object.
310+
311+ This can be achieved by passing an unsafe pointer to the object down to the
312+ C library. The C library can then include the pointer to the Rust object in
313+ the notification. This will provide a unsafe possibility to access the
314+ referenced Rust object in callback.
315+
316+ Rust code:
317+ ~~~~ {.xfail-test}
318+
319+ struct RustObject {
320+ a: i32,
321+ // other members
322+ }
323+
324+ extern fn callback(target: *RustObject, a:i32) {
325+ println!("I'm called from C with value {0}", a);
326+ (*target).a = a; // Update the value in RustObject with the value received from the callback
327+ }
328+
329+ #[link(name = "extlib")]
330+ extern {
331+ fn register_callback(target: *RustObject, cb: extern "C" fn(*RustObject, i32)) -> i32;
332+ fn trigger_callback();
333+ }
334+
335+ fn main() {
336+ // Create the object that will be referenced in the callback
337+ let rust_object = ~RustObject{a: 5, ...};
338+
339+ unsafe {
340+ // Gets a raw pointer to the object
341+ let target_addr:*RustObject = ptr::to_unsafe_ptr(rust_object);
342+ register_callback(target_addr, callback);
343+ trigger_callback(); // Triggers the callback
344+ }
345+ }
346+ ~~~~
347+
348+ C code:
349+ ~~~~ {.xfail-test}
350+ typedef void (*rust_callback)(int32_t);
351+ void* cb_target;
352+ rust_callback cb;
353+
354+ int32_t register_callback(void* callback_target, rust_callback callback) {
355+ cb_target = callback_target;
356+ cb = callback;
357+ return 1;
358+ }
359+
360+ void trigger_callback() {
361+ cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust
362+ }
363+ ~~~~
364+
365+ ## Asynchronous callbacks
366+
367+ In the already given examples the callbacks are invoked as a direct reaction
368+ to a function call to the external C library.
369+ The control over the current thread switched from Rust to C to Rust for the
370+ execution of the callback, but in the end the callback is executed on the
371+ same thread (and Rust task) that lead called the function which triggered
372+ the callback.
373+
374+ Things get more complicated when the external library spawns it's own threads
375+ and invokes callbacks from there.
376+ In these cases access to Rust data structures inside he callbacks is
377+ especially unsafe and proper synchronization mechanisms must be used.
378+ Besides classical synchronization mechanisms like mutexes one possibility in
379+ Rust is to use channels (in ` std::comm ` ) to forward data from the C thread
380+ that invoked the callback into a Rust task.
381+
382+ If an asychronous callback targets a special object in the Rust address space
383+ it is also absolutely necessary that no more callbacks are performed by the
384+ C library after the respective Rust object get's destroyed.
385+ This can be achieved by unregistering the callback it the object's
386+ destructor and designing the library in a way that guarantees that no
387+ callback will be performed after unregistration.
388+
252389# Linking
253390
254391The ` link ` attribute on ` extern ` blocks provides the basic building block for
0 commit comments