Skip to content

Commit 56d82c7

Browse files
committed
added c++-ffi example
1 parent 862babe commit 56d82c7

File tree

7 files changed

+104
-0
lines changed

7 files changed

+104
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ in a controlled repository now.
4949
* `macro-nargs.rs`: example of recursive macro
5050
* `macro-tt.rs`: macro token tree example
5151
* `nullptr.rs`: null pointer example
52+
* `c++-ffi/`: example of FFI between C, C++ and Rust

c++-ffi/Makefile

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
CC = clang
2+
CXX = clang++
3+
RUSTC = rustc -C panic="abort"
4+
5+
OBJS = add1-c.o add1-rs.a demo.o
6+
7+
TARGETS = demo-c demo-rs
8+
9+
all: $(TARGETS)
10+
11+
demo-c: demo.o add1-c.o
12+
$(CXX) -o demo-c demo.o add1-c.o
13+
14+
demo-rs: demo.o add1-rs.a
15+
$(CXX) -o demo-rs demo.o add1-rs.a -lpthread -ldl
16+
17+
add1-c.o:
18+
$(CC) -c -o add1-c.o add1.c
19+
20+
add1-rs.a: add1.rs
21+
$(RUSTC) -o add1-rs.a add1.rs
22+
23+
clean:
24+
-rm -f $(TARGETS) $(OBJS)

c++-ffi/README.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# c++-ffi: Providing a C function to C++ code from Rust or C.
2+
3+
This directory contains
4+
5+
* A C++ driver `demo.cc`
6+
7+
* A function called by the driver and written in C in `add1.c`
8+
9+
* A function called by the driver and written in Rust in
10+
`add1.rs`
11+
12+
* A `Makefile` that makes the whole thing compile
13+
14+
This has only been tested on Debian Linux with `clang` /
15+
`clang++`: other platforms and compilers might work. Who
16+
knows?
17+
18+
The `demo-rs` executable is quite large: 4MB before stripping
19+
debug symbols, 1MB after. The executable brings in big
20+
pieces of `std` for various reasons. The good news is that
21+
this scales reasonably — adding a bunch of extra Rust isn't
22+
going to change it substantially.
23+
24+
The build is controlled by `make`. One could add a fancy
25+
`build.rs` and build it all with Cargo; doesn't seem worth
26+
it here.

c++-ffi/add1.c

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <stdio.h>
2+
3+
#include <inttypes.h>
4+
int64_t add1(int64_t *x, char * msg) {
5+
*x += 1;
6+
printf("%s %ld\n", msg, *x);
7+
return *x;
8+
}

c++-ffi/add1.cc

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <iostream>
2+
3+
using namespace std;
4+
5+
extern "C" {
6+
#include <inttypes.h>
7+
int64_t add1(int64_t *x, char * msg) {
8+
*x += 1;
9+
cout << msg << " " << *x << endl;
10+
return *x;
11+
}
12+
}

c++-ffi/add1.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![crate_type = "staticlib"]
2+
3+
use std::ffi::CStr;
4+
use std::os::raw::c_char;
5+
6+
#[no_mangle]
7+
/// Add 1 to the number referenced by `x`, print the result of the add along with `msg`, return
8+
/// the result.
9+
///
10+
/// # Safety
11+
///
12+
/// `msg` must point to a valid C string, and `x` must point to a valid C `uint64_t`.
13+
pub unsafe extern "system" fn add1(x: &mut i64, msg: *const c_char) -> i64 {
14+
let msg = CStr::from_ptr(msg);
15+
*x += 1;
16+
println!("{} {}", msg.to_string_lossy(), *x);
17+
*x
18+
}

c++-ffi/demo.cc

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <iostream>
2+
3+
extern "C" {
4+
#include <inttypes.h>
5+
extern int64_t add1(int64_t *, char *);
6+
}
7+
8+
using namespace std;
9+
10+
int main() {
11+
int64_t x = 3;
12+
int64_t y = add1(&x, (char *) "working with");
13+
cout << "got " << x << " " << y << endl;
14+
return 0;
15+
}

0 commit comments

Comments
 (0)