• Stars
    star
    213
  • Rank 185,410 (Top 4 %)
  • Language
    Rust
  • Created over 2 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Embed C code at compile time inside Rust using C2Rust

embed-c

embed-c is a crate that allows you to embed C code inside Rust code files. The C code is translated into Rust code at compile time using C2Rust, which means that it is fully interoperable with Rust. C code can call Rust code, and vice-versa.

Basic usage

#![feature(rustc_private)] 

use embed_c::embed_c;

embed_c! {
    int add(int x, int y) {
        return x + y;
    }
}

fn main() {
    let x = unsafe { add(1, 2) };
    println!("{}", x);
}

Install

The library is not yet on crates.io. Clone the repository somewhere and set it up:

git clone https://github.com/zdimension/embed-c.git
cd embed-c
git submodule update --init c2rust
cp Cargo.lock ..
cd ..

and add this to your Cargo.toml:

[dependencies]
embed-c = { path = "./embed-c", version = "0.1" }

[patch.crates-io]
c2rust-transpile = { path = "./embed-c/c2rust/c2rust-transpile" }

NOTE: this crate is designed to work for the nightly-2019-12-05 version of Rust, so put this in your rust-toolchain.toml:

[toolchain]
channel = "nightly-2019-12-05"

And change the package.edition setting in your Cargo.toml to be "2018":

[package]
edition = "2018"

If you get errors about the matches! macro, or from the half or rustc_demangle crates, copy the Cargo.lock file to your project root again.

Usage details

The example at the top is translated into:

#[no_mangle]
pub unsafe extern "C" fn add(mut x: libc::c_int, mut y: libc::c_int)
 -> libc::c_int {
    return x + y;
}

fn main() {
    let x = unsafe { add(1, 2) };
    println!("{}", x);
}

The #![feature(rustc_private)] bit is required since the crate uses internal features while not being loaded from crates.io.

See more examples in src/lib.rs.

embed_c! {
    void send(to, from, count)
        register short *to, *from;
        register count;
    {
        register n = (count + 7) / 8;
        switch (count % 8) {
        case 0: do { *to++ = *from++;
        case 7:      *to++ = *from++;
        case 6:      *to++ = *from++;
        case 5:      *to++ = *from++;
        case 4:      *to++ = *from++;
        case 3:      *to++ = *from++;
        case 2:      *to++ = *from++;
        case 1:      *to++ = *from++;
                } while (--n > 0);
        }
    }
}

fn main() {
    let mut source = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let mut dest = [0; 10];
    unsafe { send(dest.as_mut_ptr(), source.as_mut_ptr(), 10); };
    assert_eq!(source, dest);
}

Here, the send function becomes:

#[no_mangle]
pub unsafe extern "C" fn send(mut to: *mut libc::c_short,
                              mut from: *mut libc::c_short,
                              mut count: libc::c_int) {
    let mut n: libc::c_int = (count + 7 as libc::c_int) / 8 as libc::c_int;
    let mut current_block_7: u64;
    match count % 8 as libc::c_int {
        0 => { current_block_7 = 8258075665625361029; }
        7 => { current_block_7 = 8412423308551259261; }
        6 => { current_block_7 = 15077176690991321518; }
        ...
        1 => { current_block_7 = 14053040055230693409; }
        _ => { current_block_7 = 13586036798005543211; }
    }
    loop  {
        match current_block_7 {
            13586036798005543211 => { return; }
            8258075665625361029 => {
                let fresh0 = from;
                from = from.offset(1);
                let fresh1 = to;
                to = to.offset(1);
                *fresh1 = *fresh0;
                current_block_7 = 8412423308551259261;
            }
            8412423308551259261 => ...
            ...
            _ => {
                let fresh14 = from;
                from = from.offset(1);
                let fresh15 = to;
                to = to.offset(1);
                *fresh15 = *fresh14;
                n -= 1;
                if n > 0 as libc::c_int {
                    current_block_7 = 8258075665625361029;
                } else { current_block_7 = 13586036798005543211; }
            }
        }
    };
}

As you can see, the interweaved switch-do construct is transpiled into a very idiomatic Rust function through the use of pattern matching. You may not like it, but this is what peak functional programming looks like.

Limitations

Many

Motivation

N/A

License

This project is licensed under either of

More Repositories

1

inline-vbs

Embed VBScript code inside Rust code files
Rust
60
star
2

parm_extended

Assembly
52
star
3

SharpBoot

SharpBoot is a program for creating multiboot ISOs by choosing other ISO files and putting them in categories.
C#
31
star
4

elecanalysis

Python
30
star
5

usbrawmap

USB scancode mapper / driver for old nonstandard keyboards
Rust
26
star
6

plexdlweb

A simple web UI for downloading media from Plex without the Plex Pass.
Python
12
star
7

hm-infer-scheme

Hindley-Milner type inference in Scheme, for Scheme
Racket
9
star
8

desktop-snake

snake in windows explorer
Rust
9
star
9

FreeRaider

Free & open-source C#-OpenTK port of http://github.com/OpenTomb/OpenTomb
C#
6
star
10

hm-infer-rs

Hindley-Milner type inference for Scheme, in Rust
Rust
5
star
11

logisim-connectfour

Connect Four implemented as a Logisim circuit
5
star
12

variant-rs

Rust
4
star
13

logisim-pong

Pong game implemented as a Logisim circuit
4
star
14

FastMark

fast, cross-platform, efficient watermarking tool
C#
4
star
15

tdalgcomp

3
star
16

cozy-banks-analysis

Python
3
star
17

pns-si3-qgl-2021-soyouz

pns-si3-qgl-2021-soyouz created by GitHub Classroom
Java
3
star
18

graphrust

graph viewer
Rust
3
star
19

tdsys

C
2
star
20

turing_projet1

Premier projet du module d'algorithmique & complexité du S7 (PNS)
2
star
21

test-tr5

it's a tr5 test
C
2
star
22

USBFastBoot

C#
2
star
23

links

Links
1
star
24

macro-forth

Compile-time const Forth evaluation with macros
Rust
1
star
25

ps7-21-22-al-caspar-21-22

ps7-21-22-al-caspar-21-22 created by GitHub Classroom
C#
1
star
26

tdcompil

C
1
star
27

phytestcs

C#
1
star
28

blog

1
star
29

polytheque

Annecy la capitale, tmtc
PHP
1
star
30

tdpmp

C++
1
star
31

parmesan

Correction officielle du projet PARM
Assembly
1
star
32

2020-2021-ps6-polytechnicois

TypeScript
1
star
33

accidents

Java
1
star
34

tdpp

Python
1
star
35

takenoko

Java
1
star
36

sudoku

Sudoku solver
C++
1
star
37

tdpf

Racket
1
star
38

security-iot-notre-projet

Python
1
star
39

instant-system-api

Documentation de l'API Instant-System utilisée par beaucoup de réseaux de transports en commun
1
star
40

Ocular

Free C# WYSIWYG HTML editor
C#
1
star