@@ -249,143 +249,6 @@ fn main() {
249
249
}
250
250
~~~~
251
251
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
-
389
252
# Linking
390
253
391
254
The ` link ` attribute on ` extern ` blocks provides the basic building block for
0 commit comments