Skip to content

Instantly share code, notes, and snippets.

@klutzy
Last active April 6, 2016 13:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save klutzy/9595004 to your computer and use it in GitHub Desktop.
Save klutzy/9595004 to your computer and use it in GitHub Desktop.
Rust/C++ ffi
#[feature(macro_rules)];
// redundant `fn` and `self`: workaround for #5902
// https://github.com/mozilla/rust/issues/5902
macro_rules! cpp_methods(
($c:ident $vt:ident {
$(fn $func:ident(self $(, $i:ident: $t:ty)*) -> $rt:ty;)*
}) => (
struct $c(*());
struct $vt {
$(
$func: extern fn(*() $(,$t)*) -> $rt,
)+
}
impl $c {
$(
unsafe fn $func(&self, $($i: $t),*) -> $rt {
let $c(this) = *self;
let vptr: *$vt = *(this as **$vt);
((*vptr).$func)(this, $($i),*)
}
)+
}
);
)
cpp_methods!(IUnknown IUnknownVtbl {
fn func1(self) -> i8;
fn func2(self, i: i8) -> i8;
})
#[link(name = "da")]
extern {
// NOTE abi difference:
// fn get_unknown() -> *(); -> declare {}* @get_unknown()
// fn get_unknown() -> IUnknown; -> declare void @get_unknown(%struct.IUnknown* sret)
fn get_unknown() -> *();
}
pub fn main() {
let p = unsafe { IUnknown(get_unknown()) };
let i1 = unsafe { p.func1() };
let i2 = unsafe { p.func2(14) };
println!("i1: {} / i2: {}", i1, i2); // 19, 16
}
typedef signed char i8;
struct IUnknown {
virtual i8 func1() = 0;
virtual i8 func2(i8) = 0;
};
struct Real: IUnknown {
virtual i8 func1() {
return 19;
}
virtual i8 func2(i8 i) {
return i + 2;
}
};
Real real;
extern "C"
IUnknown* get_unknown() {
return ℜ
}
//void test(IUnknown* iu) {
// iu->func1();
// iu->func2(2);
//}
all: a
a: a.rs libda.so
rustc a.rs -o $@ -L .
libda.so: da.cpp
clang++ $< -fPIC -shared -o $@
run: a libda.so
LD_LIBRARY_PATH=. ./a
clean:
rm -rf libda.so a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment