Skip to content
This repository was archived by the owner on Apr 8, 2026. It is now read-only.

Commit 3f9eb21

Browse files
rust: use evmc c loader replace pure rust version
1 parent 5b2cc1a commit 3f9eb21

4 files changed

Lines changed: 78 additions & 63 deletions

File tree

bindings/rust/evmc-client/Cargo.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@ license = "Apache-2.0"
1010
repository = "https://github.com/ethereum/evmc"
1111
description = "Bindings to EVMC (Client/Host specific)"
1212
edition = "2018"
13+
build = "build.rs"
1314

1415
[dependencies]
15-
evmc-sys = { path = "../evmc-sys", version = "7.4.0" }
16-
evmc-vm = { path = "../evmc-vm", version = "7.4.0" }
17-
libloading = "0.5"
16+
evmc-sys = { path = "../evmc-sys" }
17+
evmc-vm = { path = "../evmc-vm" }
18+
enum_primitive = "0.1.1"
19+
num = "0.3"
1820
lazy_static = "1.4.0"
21+
22+
[build-dependencies]
23+
cmake = "0.1.44"

bindings/rust/evmc-client/build.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (C) 2020 Second State.
2+
// This file is part of EVMC-Client.
3+
4+
// EVMC-Client is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as
6+
// published by the Free Software Foundation, either version 3 of the
7+
// License, or (at your option) any later version.
8+
9+
// EVMC-Client is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
use std::path::Path;
18+
extern crate cmake;
19+
use cmake::Config;
20+
21+
fn build_link_evmc_tools() {
22+
let dst = Config::new("../../../").build();
23+
let evmc_path = Path::new(&dst).join("build/lib/loader");
24+
println!("cargo:rustc-link-search=native={}", evmc_path.display());
25+
println!("cargo:rustc-link-lib=static=evmc-loader");
26+
}
27+
28+
fn main() {
29+
build_link_evmc_tools();
30+
}

bindings/rust/evmc-client/src/lib.rs

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
* Licensed under the Apache License, Version 2.0.
44
*/
55

6+
#[macro_use]
7+
extern crate enum_primitive;
68
pub mod host;
79
mod loader;
810
pub mod types;
9-
pub use self::loader::EvmcLoaderErrorCode;
10-
use crate::loader::evmc_load_and_create;
11+
pub use crate::loader::{load_and_create, EvmcLoaderErrorCode};
1112
use crate::types::*;
1213
use evmc_sys as ffi;
1314
use std::ffi::CStr;
@@ -16,26 +17,6 @@ extern "C" {
1617
fn evmc_create() -> *mut ffi::evmc_vm;
1718
}
1819

19-
fn error(err: EvmcLoaderErrorCode) -> Result<EvmcLoaderErrorCode, &'static str> {
20-
match err {
21-
EvmcLoaderErrorCode::EvmcLoaderSucces => Ok(EvmcLoaderErrorCode::EvmcLoaderSucces),
22-
EvmcLoaderErrorCode::EvmcLoaderCannotOpen => Err("evmc loader: library cannot open"),
23-
EvmcLoaderErrorCode::EvmcLoaderSymbolNotFound => {
24-
Err("evmc loader: the EVMC create function not found")
25-
}
26-
EvmcLoaderErrorCode::EvmcLoaderInvalidArgument => {
27-
panic!("evmc loader: filename argument is invalid")
28-
}
29-
EvmcLoaderErrorCode::EvmcLoaderInstanceCreationFailure => {
30-
Err("evmc loader: VM instance creation failure")
31-
}
32-
EvmcLoaderErrorCode::EvmcLoaderAbiVersionMismatch => {
33-
Err("evmc loader: ABI version mismatch")
34-
}
35-
_ => Err("evmc loader: unexpected error"),
36-
}
37-
}
38-
3920
pub struct EvmcVm {
4021
handle: *mut ffi::evmc_vm,
4122
host_interface: *mut ffi::evmc_host_interface,
@@ -141,13 +122,13 @@ impl EvmcVm {
141122
}
142123

143124
pub fn load(fname: &str) -> (EvmcVm, Result<EvmcLoaderErrorCode, &'static str>) {
144-
let (instance, ec) = evmc_load_and_create(fname);
125+
let (instance, ec) = load_and_create(fname);
145126
(
146127
EvmcVm {
147128
handle: instance,
148129
host_interface: Box::into_raw(Box::new(host::get_evmc_host_interface())),
149130
},
150-
error(ec),
131+
ec,
151132
)
152133
}
153134

bindings/rust/evmc-client/src/loader.rs

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,22 @@
44
*/
55

66
use evmc_sys as ffi;
7-
use libloading::{Library, Symbol};
8-
use std::ptr;
7+
use std::ffi::{CStr, CString};
8+
use std::os::raw::c_char;
99
use std::str;
10+
extern crate num;
11+
use num::FromPrimitive;
12+
13+
#[link(name = "evmc-loader")]
14+
extern "C" {
15+
fn evmc_load_and_create(
16+
filename: *const c_char,
17+
evmc_loader_error_code: *mut i32,
18+
) -> *mut ffi::evmc_vm;
19+
fn evmc_last_error_msg() -> *const c_char;
20+
}
1021

11-
type EvmcCreate = extern "C" fn() -> *mut ffi::evmc_vm;
12-
22+
enum_from_primitive! {
1323
#[derive(Debug)]
1424
pub enum EvmcLoaderErrorCode {
1525
/** The loader succeeded. */
@@ -36,39 +46,28 @@ pub enum EvmcLoaderErrorCode {
3646
/** The VM option value is invalid. */
3747
EvmcLoaderInvalidOptionValue = 7,
3848
}
49+
}
3950

40-
pub fn evmc_load_and_create(fname: &str) -> (*mut ffi::evmc_vm, EvmcLoaderErrorCode) {
41-
unsafe {
42-
let mut instance: *mut ffi::evmc_vm = ptr::null_mut();
43-
44-
let library: Library = match Library::new(fname) {
45-
Ok(lib) => lib,
46-
Err(_) => {
47-
return (instance, EvmcLoaderErrorCode::EvmcLoaderCannotOpen);
48-
}
49-
};
50-
51-
let evmc_create_fn: Symbol<EvmcCreate> = match library.get(b"evmc_create\0") {
52-
Ok(symbol) => symbol,
53-
Err(_) => {
54-
return (instance, EvmcLoaderErrorCode::EvmcLoaderSymbolNotFound);
55-
}
56-
};
57-
58-
instance = evmc_create_fn();
59-
60-
if instance.is_null() {
61-
return (
62-
instance,
63-
EvmcLoaderErrorCode::EvmcLoaderInstanceCreationFailure,
64-
);
65-
}
51+
fn error(err: EvmcLoaderErrorCode) -> Result<EvmcLoaderErrorCode, &'static str> {
52+
match err {
53+
EvmcLoaderErrorCode::EvmcLoaderSucces => Ok(EvmcLoaderErrorCode::EvmcLoaderSucces),
54+
_ => unsafe { Err(CStr::from_ptr(evmc_last_error_msg()).to_str().unwrap()) },
55+
}
56+
}
6657

67-
if (*instance).abi_version
68-
!= std::mem::transmute::<ffi::_bindgen_ty_1, i32>(ffi::EVMC_ABI_VERSION)
69-
{
70-
return (instance, EvmcLoaderErrorCode::EvmcLoaderAbiVersionMismatch);
71-
}
72-
return (instance, EvmcLoaderErrorCode::EvmcLoaderSucces);
58+
pub fn load_and_create(
59+
fname: &str,
60+
) -> (
61+
*mut ffi::evmc_vm,
62+
Result<EvmcLoaderErrorCode, &'static str>,
63+
) {
64+
let c_str = CString::new(fname).unwrap();
65+
unsafe {
66+
let mut error_code: i32 = 0;
67+
let instance = evmc_load_and_create(c_str.as_ptr() as *const c_char, &mut error_code);
68+
return (
69+
instance,
70+
error(EvmcLoaderErrorCode::from_i32(error_code).unwrap()),
71+
);
7372
}
7473
}

0 commit comments

Comments
 (0)