Last active
December 20, 2021 11:01
-
-
Save Connicpu/2139239f30c633f6450e to your computer and use it in GitHub Desktop.
Poking a Rust vtable from C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(box_syntax)] | |
pub struct MyThing { | |
stuff: Vec<i32>, | |
} | |
pub trait DoAThing { | |
fn add(&mut self, item: i32); | |
fn remove(&mut self) -> i32; | |
} | |
impl DoAThing for MyThing { | |
fn add(&mut self, item: i32) { | |
self.stuff.push(item); | |
} | |
fn remove(&mut self) -> i32 { | |
match self.stuff.pop() { | |
Some(value) => value, | |
None => 0, | |
} | |
} | |
} | |
#[no_mangle] | |
pub extern "C" fn new_thing() -> Box<DoAThing> { | |
box MyThing { stuff: vec![] } | |
} | |
#[no_mangle] | |
pub extern "C" fn free_thing(_: Box<DoAThing>) { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <stdint.h> | |
#include <assert.h> | |
struct DoAThingVtable | |
{ | |
void(*destructor)(void *self); | |
size_t size; | |
size_t alignment; | |
void(*add)(void *self, int32_t item); | |
int32_t(*remove)(void *self); | |
}; | |
struct BoxDoAThing | |
{ | |
void *data; | |
DoAThingVtable *vtable; | |
}; | |
int main(void) | |
{ | |
auto lib = LoadLibrary(TEXT("doathing.dll")); | |
auto new_thing = (BoxDoAThing(*)()) GetProcAddress(lib, "new_thing"); | |
auto free_thing = (void(*)(BoxDoAThing)) GetProcAddress(lib, "free_thing"); | |
auto thing = new_thing(); | |
thing.vtable->add(thing.data, 5); | |
thing.vtable->add(thing.data, 6); | |
assert(thing.vtable->remove(thing.data) == 6); | |
assert(thing.vtable->remove(thing.data) == 5); | |
assert(thing.vtable->remove(thing.data) == 0); | |
free_thing(thing); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment