mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-25 15:29:43 -05:00
works
This commit is contained in:
parent
f6bc61ec11
commit
f9d0a6ba77
5 changed files with 119 additions and 49 deletions
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"rust.clippy_preference": "on"
|
||||
"C_Cpp.clang_format_style": "Chromium"
|
||||
}
|
|
@ -4,5 +4,6 @@ version = "0.1.0"
|
|||
authors = ["Bert Belder <bertbelder@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
[build-dependencies]
|
||||
cc = "1.0.45"
|
||||
|
||||
|
|
10
build.rs
Normal file
10
build.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use cc;
|
||||
|
||||
fn main() {
|
||||
cc::Build::new()
|
||||
.cpp(true)
|
||||
.flag("-std:c++17")
|
||||
.debug(true)
|
||||
.file("src/lib.cpp")
|
||||
.compile("v8-bindings");
|
||||
}
|
64
src/lib.cpp
Normal file
64
src/lib.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace v8 {
|
||||
class Channel {
|
||||
public:
|
||||
Channel() {}
|
||||
virtual ~Channel() {}
|
||||
|
||||
virtual void method1(int32_t arg) {
|
||||
std::cout << "default v8::Channel::method1(" << arg << ") called"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
virtual int32_t method2() const = 0;
|
||||
};
|
||||
} // namespace v8
|
||||
|
||||
extern "C" {
|
||||
void v8__Channel__EXTENDER__method1(v8::Channel& self, int32_t arg);
|
||||
int32_t v8__Channel__EXTENDER__method2(const v8::Channel& self);
|
||||
}
|
||||
|
||||
namespace extender {
|
||||
template <class T>
|
||||
using uninit_t = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
|
||||
|
||||
namespace v8 {
|
||||
struct Channel : public ::v8::Channel {
|
||||
using ::v8::Channel::Channel;
|
||||
|
||||
void method1(int32_t arg) override {
|
||||
v8__Channel__EXTENDER__method1(*this, arg);
|
||||
}
|
||||
|
||||
int32_t method2() const override {
|
||||
return v8__Channel__EXTENDER__method2(*this);
|
||||
}
|
||||
};
|
||||
} // namespace v8
|
||||
} // namespace extender
|
||||
|
||||
extern "C" {
|
||||
void v8__Channel__DTOR(v8::Channel& self) {
|
||||
self.~Channel();
|
||||
}
|
||||
void v8__Channel__method1(v8::Channel& self, int32_t arg) {
|
||||
self.method1(arg);
|
||||
}
|
||||
void v8__Channel__Channel__method1(v8::Channel& self, int32_t arg) {
|
||||
self.::v8::Channel::method1(arg);
|
||||
}
|
||||
int32_t v8__Channel__method2(const v8::Channel& self) {
|
||||
return self.method2();
|
||||
}
|
||||
void v8__Channel__EXTENDER__CTOR(
|
||||
extender::uninit_t<extender::v8::Channel>& buf) {
|
||||
new (std::launder(&buf)) extender::v8::Channel();
|
||||
}
|
||||
} // extern "C"
|
89
src/main.rs
89
src/main.rs
|
@ -3,19 +3,37 @@ mod channel {
|
|||
|
||||
extern "C" {
|
||||
// Call a method/destructor; virtual methods use C++ dynamic dispatch.
|
||||
fn Channel__DTOR(this: &mut Channel) -> ();
|
||||
fn Channel__method1(this: &mut Channel) -> ();
|
||||
fn Channel__method2(this: &Channel) -> i32;
|
||||
fn v8__Channel__DTOR(this: &mut Channel) -> ();
|
||||
fn v8__Channel__method1(this: &mut Channel, arg: i32) -> ();
|
||||
fn v8__Channel__method2(this: &Channel) -> i32;
|
||||
|
||||
// Call a method of a specific class implementation, bypassing dynamic
|
||||
// dispatch. C++ equivalent: `my_channel.Channel::a()`.
|
||||
fn Channel__Channel__method1(this: &mut Channel) -> ();
|
||||
fn v8__Channel__Channel__method1(this: &mut Channel, arg: i32) -> ();
|
||||
|
||||
// Constructs a special class derived from Channel that forwards all
|
||||
// virtual method invocations to rust. It is assumed that this subclass
|
||||
// has the same size and memory layout as the class it's deriving from.
|
||||
fn Channel__EXTENDER__CTOR(this: &mut std::mem::MaybeUninit<Channel>)
|
||||
-> ();
|
||||
fn v8__Channel__EXTENDER__CTOR(
|
||||
buf: &mut std::mem::MaybeUninit<Channel>,
|
||||
) -> ();
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn v8__Channel__EXTENDER__method1(
|
||||
this: &mut Channel,
|
||||
arg: i32,
|
||||
) {
|
||||
ChannelExtender::dispatch_mut(this).method1(arg)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn v8__Channel__EXTENDER__method2(
|
||||
this: &Channel,
|
||||
) -> i32 {
|
||||
ChannelExtender::dispatch(this).method2()
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -24,17 +42,17 @@ mod channel {
|
|||
}
|
||||
|
||||
impl Channel {
|
||||
pub fn method1(&mut self) {
|
||||
unsafe { Channel__method1(self) }
|
||||
pub fn method1(&mut self, arg: i32) {
|
||||
unsafe { v8__Channel__method1(self, arg) }
|
||||
}
|
||||
pub fn method2(&self) -> i32 {
|
||||
unsafe { Channel__method2(self) }
|
||||
unsafe { v8__Channel__method2(self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Channel {
|
||||
fn drop(&mut self) {
|
||||
unsafe { Channel__DTOR(self) }
|
||||
unsafe { v8__Channel__DTOR(self) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,15 +70,6 @@ mod channel {
|
|||
}
|
||||
}
|
||||
|
||||
//impl AsChannel for ChannelExtender {
|
||||
// fn as_channel(&self) -> &Channel {
|
||||
// &self.cxx_channel
|
||||
// }
|
||||
// fn as_channel_mut(&mut self) -> &mut Channel {
|
||||
// &mut self.cxx_channel
|
||||
// }
|
||||
//}
|
||||
|
||||
impl<T> AsChannel for T
|
||||
where
|
||||
T: ChannelOverrides,
|
||||
|
@ -75,8 +84,8 @@ mod channel {
|
|||
|
||||
pub struct ChannelDefaults;
|
||||
impl ChannelDefaults {
|
||||
pub fn method1(channel: &mut Channel) {
|
||||
unsafe { Channel__Channel__method1(channel) }
|
||||
pub fn method1(channel: &mut Channel, arg: i32) {
|
||||
unsafe { v8__Channel__Channel__method1(channel, arg) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,8 +93,8 @@ mod channel {
|
|||
fn extender(&self) -> &ChannelExtender;
|
||||
fn extender_mut(&mut self) -> &mut ChannelExtender;
|
||||
|
||||
fn method1(&mut self) {
|
||||
ChannelDefaults::method1(self.as_channel_mut())
|
||||
fn method1(&mut self, arg: i32) {
|
||||
ChannelDefaults::method1(self.as_channel_mut(), arg)
|
||||
}
|
||||
fn method2(&self) -> i32;
|
||||
}
|
||||
|
@ -97,26 +106,10 @@ mod channel {
|
|||
}
|
||||
|
||||
impl ChannelExtender {
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn Channel__EXTENDER__method1__DISPATCH(
|
||||
this: &mut Channel,
|
||||
) {
|
||||
ChannelExtender::dispatch_mut(this).method1()
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn Channel__EXTENDER__method2__DISPATCH(
|
||||
this: &Channel,
|
||||
) -> i32 {
|
||||
ChannelExtender::dispatch(this).method2()
|
||||
}
|
||||
|
||||
fn construct_cxx_channel() -> Channel {
|
||||
unsafe {
|
||||
let mut buf = std::mem::MaybeUninit::<Channel>::uninit();
|
||||
Channel__EXTENDER__CTOR(&mut buf);
|
||||
v8__Channel__EXTENDER__CTOR(&mut buf);
|
||||
buf.assume_init()
|
||||
}
|
||||
}
|
||||
|
@ -162,13 +155,13 @@ mod channel {
|
|||
})
|
||||
}
|
||||
|
||||
unsafe fn dispatch(channel: &Channel) -> &dyn ChannelOverrides {
|
||||
pub unsafe fn dispatch(channel: &Channel) -> &dyn ChannelOverrides {
|
||||
let this = Self::get_channel_offset().to_embedder::<Self>(channel);
|
||||
let embedder = this.extender_offset.to_embedder::<util::Opaque>(this);
|
||||
std::mem::transmute((embedder, this.rust_vtable))
|
||||
}
|
||||
|
||||
unsafe fn dispatch_mut(channel: &mut Channel) -> &mut dyn ChannelOverrides {
|
||||
pub unsafe fn dispatch_mut(channel: &mut Channel) -> &mut dyn ChannelOverrides {
|
||||
let this = Self::get_channel_offset().to_embedder_mut::<Self>(channel);
|
||||
let vtable = this.rust_vtable;
|
||||
let embedder = this.extender_offset.to_embedder_mut::<util::Opaque>(this);
|
||||
|
@ -242,12 +235,14 @@ mod example {
|
|||
fn extender_mut(&mut self) -> &mut ChannelExtender {
|
||||
&mut self.channel_extender
|
||||
}
|
||||
fn method1(&mut self) {
|
||||
println!("overriden a() called");
|
||||
self.a += self.b;
|
||||
fn method1(&mut self, arg: i32) {
|
||||
println!("overriden method1({}) called", arg);
|
||||
self.a += self.b * arg;
|
||||
let arg = self.a;
|
||||
ChannelDefaults::method1(self.as_channel_mut(), arg);
|
||||
}
|
||||
fn method2(&self) -> i32 {
|
||||
println!("overriden b() called");
|
||||
println!("overriden method2() called");
|
||||
self.a * self.b
|
||||
}
|
||||
}
|
||||
|
@ -268,6 +263,6 @@ fn main() {
|
|||
use example::*;
|
||||
let mut ex = Example::new();
|
||||
let chan = ex.as_channel_mut();
|
||||
chan.method1();
|
||||
chan.method1(3);
|
||||
println!("{}", chan.method2());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue