diff --git a/bindings/rust/evmc-client/Cargo.toml b/bindings/rust/evmc-client/Cargo.toml
index 63e7abae3..ad4f82e91 100644
--- a/bindings/rust/evmc-client/Cargo.toml
+++ b/bindings/rust/evmc-client/Cargo.toml
@@ -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"
diff --git a/bindings/rust/evmc-client/build.rs b/bindings/rust/evmc-client/build.rs
new file mode 100644
index 000000000..07b68b437
--- /dev/null
+++ b/bindings/rust/evmc-client/build.rs
@@ -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 .
+
+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();
+}
diff --git a/bindings/rust/evmc-client/src/lib.rs b/bindings/rust/evmc-client/src/lib.rs
index c1f895805..c71a5ebf1 100644
--- a/bindings/rust/evmc-client/src/lib.rs
+++ b/bindings/rust/evmc-client/src/lib.rs
@@ -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;
@@ -16,26 +17,6 @@ extern "C" {
fn evmc_create() -> *mut ffi::evmc_vm;
}
-fn error(err: EvmcLoaderErrorCode) -> Result {
- 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,
@@ -141,13 +122,13 @@ impl EvmcVm {
}
pub fn load(fname: &str) -> (EvmcVm, Result) {
- 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,
)
}
diff --git a/bindings/rust/evmc-client/src/loader.rs b/bindings/rust/evmc-client/src/loader.rs
index 0bba06c9a..757b97675 100644
--- a/bindings/rust/evmc-client/src/loader.rs
+++ b/bindings/rust/evmc-client/src/loader.rs
@@ -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. */
@@ -36,39 +46,28 @@ 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 = 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 {
+ 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::EVMC_ABI_VERSION)
- {
- return (instance, EvmcLoaderErrorCode::EvmcLoaderAbiVersionMismatch);
- }
- return (instance, EvmcLoaderErrorCode::EvmcLoaderSucces);
+pub fn load_and_create(
+ fname: &str,
+) -> (
+ *mut ffi::evmc_vm,
+ Result,
+) {
+ 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()),
+ );
}
}