Skip to content

Commit

Permalink
rust: use evmc c loader replace pure rust version
Browse files Browse the repository at this point in the history
  • Loading branch information
CaptainVincent committed Jul 20, 2020
1 parent 5b2cc1a commit 5b2b4f2
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 63 deletions.
11 changes: 8 additions & 3 deletions bindings/rust/evmc-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ license = "Apache-2.0"
repository = "https://github.com/ethereum/evmc"
description = "Bindings to EVMC (Client/Host specific)"
edition = "2018"
build = "build.rs"

[dependencies]
evmc-sys = { path = "../evmc-sys", version = "7.4.0" }
evmc-vm = { path = "../evmc-vm", version = "7.4.0" }
libloading = "0.5"
evmc-sys = { path = "../evmc-sys" }
evmc-vm = { path = "../evmc-vm" }
enum_primitive = "0.1.1"
num = "0.3"
lazy_static = "1.4.0"

[build-dependencies]
cmake = "0.1.44"
30 changes: 30 additions & 0 deletions bindings/rust/evmc-client/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2020 Second State.
// This file is part of EVMC-Client.

// EVMC-Client is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.

// EVMC-Client is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use std::path::Path;
extern crate cmake;
use cmake::Config;

fn build_link_evmc_tools() {
let dst = Config::new("../../../").build();
let evmc_path = Path::new(&dst).join("build/lib/loader");
println!("cargo:rustc-link-search=native={}", evmc_path.display());
println!("cargo:rustc-link-lib=static=evmc-loader");
}

fn main() {
build_link_evmc_tools();
}
29 changes: 5 additions & 24 deletions bindings/rust/evmc-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* Licensed under the Apache License, Version 2.0.
*/

#[macro_use]
extern crate enum_primitive;
pub mod host;
mod loader;
pub mod types;
pub use self::loader::EvmcLoaderErrorCode;
use crate::loader::evmc_load_and_create;
pub use crate::loader::{load_and_create, EvmcLoaderErrorCode};
use crate::types::*;
use evmc_sys as ffi;
use std::ffi::CStr;
Expand All @@ -16,26 +17,6 @@ extern "C" {
fn evmc_create() -> *mut ffi::evmc_vm;
}

fn error(err: EvmcLoaderErrorCode) -> Result<EvmcLoaderErrorCode, &'static str> {
match err {
EvmcLoaderErrorCode::EvmcLoaderSucces => Ok(EvmcLoaderErrorCode::EvmcLoaderSucces),
EvmcLoaderErrorCode::EvmcLoaderCannotOpen => Err("evmc loader: library cannot open"),
EvmcLoaderErrorCode::EvmcLoaderSymbolNotFound => {
Err("evmc loader: the EVMC create function not found")
}
EvmcLoaderErrorCode::EvmcLoaderInvalidArgument => {
panic!("evmc loader: filename argument is invalid")
}
EvmcLoaderErrorCode::EvmcLoaderInstanceCreationFailure => {
Err("evmc loader: VM instance creation failure")
}
EvmcLoaderErrorCode::EvmcLoaderAbiVersionMismatch => {
Err("evmc loader: ABI version mismatch")
}
_ => Err("evmc loader: unexpected error"),
}
}

pub struct EvmcVm {
handle: *mut ffi::evmc_vm,
host_interface: *mut ffi::evmc_host_interface,
Expand Down Expand Up @@ -141,13 +122,13 @@ impl EvmcVm {
}

pub fn load(fname: &str) -> (EvmcVm, Result<EvmcLoaderErrorCode, &'static str>) {
let (instance, ec) = evmc_load_and_create(fname);
let (instance, ec) = load_and_create(fname);
(
EvmcVm {
handle: instance,
host_interface: Box::into_raw(Box::new(host::get_evmc_host_interface())),
},
error(ec),
ec,
)
}

Expand Down
68 changes: 32 additions & 36 deletions bindings/rust/evmc-client/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@
*/

use evmc_sys as ffi;
use libloading::{Library, Symbol};
use std::ptr;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::str;
extern crate num;
use num::FromPrimitive;

#[link(name = "evmc-loader")]
extern "C" {
fn evmc_load_and_create(
filename: *const c_char,
evmc_loader_error_code: *mut i32,
) -> *mut ffi::evmc_vm;
fn evmc_last_error_msg() -> *const c_char;
}

type EvmcCreate = extern "C" fn() -> *mut ffi::evmc_vm;

enum_from_primitive! {
#[derive(Debug)]
pub enum EvmcLoaderErrorCode {
/** The loader succeeded. */
Expand All @@ -36,39 +46,25 @@ pub enum EvmcLoaderErrorCode {
/** The VM option value is invalid. */
EvmcLoaderInvalidOptionValue = 7,
}
}

pub fn evmc_load_and_create(fname: &str) -> (*mut ffi::evmc_vm, EvmcLoaderErrorCode) {
unsafe {
let mut instance: *mut ffi::evmc_vm = ptr::null_mut();

let library: Library = match Library::new(fname) {
Ok(lib) => lib,
Err(_) => {
return (instance, EvmcLoaderErrorCode::EvmcLoaderCannotOpen);
}
};

let evmc_create_fn: Symbol<EvmcCreate> = match library.get(b"evmc_create\0") {
Ok(symbol) => symbol,
Err(_) => {
return (instance, EvmcLoaderErrorCode::EvmcLoaderSymbolNotFound);
}
};

instance = evmc_create_fn();

if instance.is_null() {
return (
instance,
EvmcLoaderErrorCode::EvmcLoaderInstanceCreationFailure,
);
}
fn error(err: EvmcLoaderErrorCode) -> Result<EvmcLoaderErrorCode, &'static str> {
match err {
EvmcLoaderErrorCode::EvmcLoaderSucces => Ok(EvmcLoaderErrorCode::EvmcLoaderSucces),
_ => unsafe { Err(CStr::from_ptr(evmc_last_error_msg()).to_str().unwrap()) },
}
}

if (*instance).abi_version
!= std::mem::transmute::<ffi::_bindgen_ty_1, i32>(ffi::EVMC_ABI_VERSION)
{
return (instance, EvmcLoaderErrorCode::EvmcLoaderAbiVersionMismatch);
}
return (instance, EvmcLoaderErrorCode::EvmcLoaderSucces);
pub fn load_and_create(
fname: &str,
) -> (*mut ffi::evmc_vm, Result<EvmcLoaderErrorCode, &'static str>) {
let c_str = CString::new(fname).unwrap();
unsafe {
let mut error_code: i32 = 0;
let instance = evmc_load_and_create(c_str.as_ptr() as *const c_char, &mut error_code);
return (
instance,
error(EvmcLoaderErrorCode::from_i32(error_code).unwrap()),
);
}
}

0 comments on commit 5b2b4f2

Please sign in to comment.