scribble

Tibi's blog

About LinkedIn GitHub

14 Mar 2015
Using the Rust runtime from C

I’m investigating Rust as a successor of C. In my previous post I talked about the interoperability between the two languange but be honest I just used Rust as a higher level language. I didn’t create threads, channels but Rust is very good in the area of concurrency.

In this post I walk through a very simple library which demonstrates how to create a thread in Rust and feed it from C. All the communication will go through a channel and the main thread will wait for the completion of the worker thread.

You can find the source code: [1].

Inner workings

There is a struct defined called ChannelWrapper. It ownes a channel and a join guard. We can use this struct to send values into the worker thread (through the channel) and it controls the thread’s lifetime. When an instance of this struct is being freed, it signals the worker thread to stop.

The worker thread contains a loop. It blocks on a receiving channel so every time we send a value it processes it and blocks again. I use an Option<> enum to control this loop: by sending a None the processing will step out of the loop and the thread stops.

It has some relevant associated functions:

  • channel_wrapper_create(): it creates a ChannelWrapper structure and spawns a thread. The thread runs a blocking iterator.
  • channel_wrapper_send(): send a value into the channel
  • channel_wrapper_free(): frees the struct and waits for the spawned worker thread for completion.

Usage

You will find the following files after you cloned the repo:

  • chan.rs: this is the library written in Rust
  • chan.h: the library exports some functions and this file contains the function prototypes
  • main.c: it’s a C program which uses the library
  • Makefile: you can use this file to build all executables and the library.

You can build the binaries by typing make into a terminal:

$ make
rustc -g chan.rs --crate-type dylib
gcc -Wall main.c -L. -lchan -o main
rustc -g chan.rs

There is an identical main function both in main.c and chan.rs.

After everything was built you can check the functionality by running chan:

$ ./chan
channel_wrapper_create()
channel_wrapper_send(0)
channel_wrapper_send(1)
channel_wrapper_send(2)
channel_wrapper_send(3)
...

To run the C program you have to set LB_LIBRARY_PATH to the current directory:

$ LD_LIBRARY_PATH=. ./main
channel_wrapper_create()
channel_wrapper_send(0)
channel_wrapper_send(1)
channel_wrapper_send(2)
channel_wrapper_send(3)
channel_wrapper_send(4)
...

You may look at the Makefile which contains some useful information about building and linking to Rust code.

[1] https://github.com/ihrwein/cchan


Till next time,
Tibor Benke at 00:00

scribble

About LinkedIn GitHub