I'm newbie in Rust, and trying to compile Rust code into WASM:
use libloading::{Library, Symbol};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn main() {
// Load the DLL
let lib = unsafe { Library::new("file.dll").unwrap() };
let connect: Symbol<unsafe extern "C" fn(*const std::os::raw::c_char, *const std::os::raw::c_char) -> i32;> =
unsafe { lib.get(b"Function\0").unwrap() };
But when i run wasm-pack i'm getting the error:
error[E0432]: unresolved imports 'libloading::Library', 'libloading::Symbol'
--> src\lib.rs:1:18
|
1 | use libloading::{Library, Symbol};
| ^^^^^^^ ^^^^^^ no 'Symbol' in the root
| |
| no 'Library' in the root
For more information about this error, try 'rustc --explain E0432'`.
error: could not compile 'rust' due to previous error
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute 'cargo build': exited with exit code: 101
full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"`
If my undestanding is right - libloading can'not complie to WASM.
Does any one know way to comple such Rust code into WASM? Or may be there is any other approach to access functions from dll file in JS (React).
I'm trying:
change 'release' in toml file;
compile in binary file;
Trying to compile following rust code to wasm to make it compatible running with existing js. Trying to return hashmaped value from function.
lib.rs
use wasm_bindgen::prelude::*;
use std::collections::HashMap;
#[wasm_bindgen]
pub fn get_transformed_filters()-> HashMap<i32, i32> {
let mut hm = HashMap::new();
for i in 1..9990000 {
hm.insert(i + i, i * i);
}
return hm
}
Console error after running command wasm-pack build
[INFO]: 🎯 Checking for the Wasm target...
[INFO]: 🌀 Compiling to Wasm...
Compiling hello-wasm v0.1.0 (/Users/mfe/ui/rustService/test-wasm)
error[E0277]: the trait bound `HashMap<i32, i32>: IntoWasmAbi` is not satisfied
--> src/lib.rs:15:1
|
15 | #[wasm_bindgen]
| ^^^^^^^^^^^^^^^ the trait `IntoWasmAbi` is not implemented for `HashMap<i32, i32>`
|
= note: required because of the requirements on the impl of `ReturnWasmAbi` for `HashMap<i32, i32>`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: could not compile `test-wasm`
To learn more, run the command again with --verbose.
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute `cargo build`: exited with exit code: 101
full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown"
Is there any way to achieve this ?
I'm new to rust and started experimenting with actix_web and sqlx. the goal is to create a simple, open-source Blog engine, but after I implemented the CLI argument parser and basic SQL connection pool, the code doesn't compile anymore. I'm getting the following error:
error[E0308]: mismatched types
--> src/main.rs:17:1
|
17 | #[actix_web::main]
| ^^^^^^^^^^^^^^^^^^
| |
| expected enum `std::result::Result`, found `()`
| help: try using a variant of the expected enum: `Ok(#[actix_web::main])`
18 | async fn main() -> std::io::Result<()> {
| ------------------- expected `std::result::Result<(), std::io::Error>` because of return type
|
= note: expected enum `std::result::Result<(), std::io::Error>`
found unit type `()`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rusty_read`.
To learn more, run the command again with --verbose.
the error suggests to use std::result::Result<(), std::io::Error> as return type, but I get the same error when replacing the current return type with it:
error[E0308]: mismatched types
--> src/main.rs:17:1
|
17 | #[actix_web::main]
| ^^^^^^^^^^^^^^^^^^
| |
| expected enum `std::result::Result`, found `()`
| help: try using a variant of the expected enum: `Ok(#[actix_web::main])`
18 | async fn main() -> std::result::Result<(), std::io::Error> {
| --------------------------------------- expected `std::result::Result<(), std::io::Error>` because of return type
|
= note: expected enum `std::result::Result<(), std::io::Error>`
found unit type `()`
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rusty_read`.
To learn more, run the command again with --verbose.
so far I couldn't find anybody with the same issue and could not find any reason for it.
My Code:
/Cargo.toml
[package]
name = "rusty_read"
version = "0.1.0"
authors = ["LeMoonStar <webmaster#unitcore.de>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "3.0.0-beta.1"
rust-ini = "0.15"
sqlx = { version = "0.4.0-beta.1", features = [ "all-databases", "any", "tls" ] }
clap = "2"
/src/main.rs
use actix_web::{get, web, App, HttpServer, Responder};
use ini::Ini;
use sqlx::pool::Pool;
use sqlx::any;
#[get("/")]
async fn index() -> impl Responder {
format!("index")
}
#[get("/article/{id}")]
async fn article(info: web::Path<u32>) -> impl Responder {
format!("article nr.{}", info)
}
#[actix_web::main]
async fn main() -> std::result::Result<(), std::io::Error> {
let conf = Ini::load_from_file("conf.ini").unwrap_or(Ini::load_from_str("[Server]
bindAddress = \"127.0.0.1:8080\"
[Database]
url = \"mysql://user:password#localhost/blog\"
").unwrap());
let matches = clap::App::new("Rusty Read")
.version("0.1 INDEV")
.author("LeMoonStar <webmaster#unitcore.de>")
.about("a blog engine written in rust")
.subcommand(clap::SubCommand::with_name("config")
.about("sets various configurations for the blog")
.arg(clap::Arg::with_name("address")
.short("a")
.long("adress")
.help("sets the address the http server binds on (eg. 127.0.0.1:8080)")
.takes_value(true))
.arg(clap::Arg::with_name("database")
.short("d")
.long("database")
.help("sets the url to the database (eg. mysql://user:password#localhost/blog)")
.takes_value(true)))
.subcommand(clap::SubCommand::with_name("init_database")
.about("Initializes the database which is set in the conf.ini file (or with the config command)"))
.get_matches();
if let Some(matches) = matches.subcommand_matches("config") {
if matches.is_present("address") {
conf.section(Some("Server")).unwrap()
.insert("bindAddress", "127.0.0.1:8080");
}
if matches.is_present("database") {
conf.section(Some("Database")).unwrap()
.insert("url", "mysql://user:password#localhost/blog");
}
} else if let Some(matches) = matches.subcommand_matches("init_database") {
} else {
let mut section = conf.section(Some("Server")).expect("conf.ini requires a [Server] section.");
let bind_address = section.get("bindAddress").expect("conf.ini's [Server] section requires a bindAdress.");
section = conf.section(Some("Database")).expect("conf.ini requires a [Database] section.");
let db_url = section.get("url").expect("conf.ini's [Database] section requires a url.");
let pool = Pool::<any::Any>::connect(db_url).await.expect("database connection pool could not be created.");
HttpServer::new(move || {
App::new()
.service(article)
.service(index)
.data(pool.clone())
})
.bind(bind_address).expect("could not bind http server")
.run()
.await;
}
}
I hope someone can help me with this problem since I can't continue to work on the project, while this problem is present.
the Ok(()) is actually working.. I've tried to copy-pasting all of your code before, and do cargo check i got the same problem as you write there on the comment. then I tried to clean the code inside the main function and then copy-pasting your code again piece by piece. after adding Ok(()) as the return of the main. and the error changed before I even finished the copy-pasting. see
the screenshot of different error on my local.
then I tried to fix it by adding clone() like below:
..
conf.section(Some("Server")).unwrap().clone()
..
conf.section(Some("Database")).unwrap().clone()
..
and then I cargo run it. and the server works fine! see the screenshot here.
The error is shown when i follow step to expose the contracts pallet api.
https://substrate.dev/docs/en/tutorials/add-a-pallet-to-your-runtime/#install-the-node-template
I followed the steps all the way and fixed another error that was associating the ContractExecResult::Success. Now i have trouble with these 2 errors.
I believe it has something to do with its syntax or maybe an updated library api that the tutorial has not updated to yet.
$ cargo check -p node-template-runtime
Compiling node-template-runtime v2.0.0-rc5 (C:\substrate-node-template2\runtime)
error: failed to run custom build command for `node-template-runtime v2.0.0-rc5 (C:\substrate-node-template2\runtime)`
Caused by:
process didn't exit successfully: `C:\substrate-node-template2\target\debug\build\node-template-runtime-8af1699a702fd7e8\build-script-build` (exit code: 1)
--- stdout
Executing build command: "rustup" "run" "nightly" "cargo" "rustc" "--target=wasm32-unknown-unknown" "--manifest-path=C:\\substrate-node-template2\\target\\debug\\wbuild\\node-template-runtime\\Cargo.toml" "--color=always" "--release"
--- stderr
Compiling wasm-build-runner-impl v1.0.0 (C:\substrate-node-template2\target\debug\wbuild-runner\node-template-runtime6610820868370414452)
Finished dev [unoptimized + debuginfo] target(s) in 0.75s
Running `C:\substrate-node-template2\target\debug\wbuild-runner\node-template-runtime6610820868370414452\target\x86_64-pc-windows-msvc\debug\wasm-build-runner-impl.exe`
Compiling node-template-runtime v2.0.0-rc5 (C:\substrate-node-template2\runtime)
error[E0308]: mismatched types
--> C:\substrate-node-template2\runtime\src\lib.rs:477:17
|
476 | match exec_result {
| ----------- this expression has type `(core::result::Result<pallet_contracts::ExecReturnValue, sp_runtime::DispatchError>, u64)`
477 | Ok(v) => ContractExecResult::Success{
| ^^^^^ expected tuple, found enum `core::result::Result`
|
= note: expected tuple `(core::result::Result<pallet_contracts::ExecReturnValue, sp_runtime::DispatchError>, u64)`
found enum `core::result::Result<_, _>`
error[E0308]: mismatched types
--> C:\substrate-node-template2\runtime\src\lib.rs:482:17
|
476 | match exec_result {
| ----------- this expression has type `(core::result::Result<pallet_contracts::ExecReturnValue, sp_runtime::DispatchError>, u64)`
...
482 | Err(_) => ContractExecResult::Error,
| ^^^^^^ expected tuple, found enum `core::result::Result`
|
= note: expected tuple `(core::result::Result<pallet_contracts::ExecReturnValue, sp_runtime::DispatchError>, u64)`
found enum `core::result::Result<_, _>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.
error: could not compile `node-template-runtime`.
To learn more, run the command again with --verbose.
error: process didn't exit successfully: `C:\substrate-node-template2\target\debug\wbuild-runner\node-template-runtime6610820868370414452\target\x86_64-pc-windows-msvc\debug\wasm-build-runner-impl.exe` (exit code: 1)
here is the code that is in runtime\src\lib.rs that the tutorial had me add that is causing the issue, and my modified code where 'flags' and 'gas_consumed' is added and 'status' was removed.
/*** Add This Block ***/
impl contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>
for Runtime
{
fn call(
origin: AccountId,
dest: AccountId,
value: Balance,
gas_limit: u64,
input_data: Vec<u8>,
) -> ContractExecResult {
let exec_result =
Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);
match exec_result {
Ok(v) => ContractExecResult::Success{
flags: v.status,
data: v.data,
gas_consumed: v.gas_consumed,
},
Err(_) => ContractExecResult::Error,
}
}
fn get_storage(
address: AccountId,
key: [u8; 32],
) -> contracts_primitives::GetStorageResult {
Contracts::get_storage(address, key)
}
fn rent_projection(
address: AccountId,
) -> contracts_primitives::RentProjectionResult<BlockNumber> {
Contracts::rent_projection(address)
}
}
/*** End Added Block ***/
Based on the output, it looks like you are using version 2.0.0-rc5 of the node template. At the moment, the Contracts pallet tutorial is up-to-date as of v2.0.0-rc4. Can you clone the node template from that branch and use that as a starting point? git clone -b v2.0.0-rc4 --depth 1 https://github.com/substrate-developer-hub/substrate-node-template
Starting v2.0.0-rc5, the bare_call function in Contracts pallet returns ExecResult and Gas, which can be seen at line 633, whereas only ExecResult is returned on the previous version of the Contracts pallet.
In order to continue with the tutorial, I did some tweaks with the provided code snippet in the tutorial. Here's the version of my code.
fn call(
origin: AccountId,
dest: AccountId,
value: Balance,
gas_limit: u64,
input_data: Vec<u8>,
) -> ContractExecResult {
let exec_result =
Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);
match exec_result {
(Ok(v), gas) => ContractExecResult::Success {
flags: v.flags.bits(),
data: v.data,
gas_consumed: gas,
},
(Err(_), _) => ContractExecResult::Error,
}
}
Note: I'm fairly new with Rust so my code is probably not the most optimal solution.
I want to ensure the code style is consistent by requiring this:
fn calc() -> u32 {
return 1 + 1;
}
And forbidding this:
fn calc() -> u32 {
1 + 1
}
Is there any setting in Cargo.toml?
I don't believe this can be done with Cargo itself, but Clippy has a lint for exactly this.
To enable the lint, place the line #![deny(clippy::implicit_return)] at the top of your root file (usually main.rs or lib.rs). Now running cargo clippy should show an error if you use implicit returns. You'll probably also want to disable the lint that has the opposite warning: #![allow(clippy::needless_return)].
Example code:
#![deny(clippy::implicit_return)]
#![allow(clippy::needless_return)]
fn foo() -> u32 {
0
}
fn main() {
println!("{}", foo());
}
And the error after running cargo clippy:
error: missing return statement
--> src/main.rs:5:5
|
5 | 0
| ^ help: add `return` as shown: `return 0`
|
note: lint level defined here
--> src/main.rs:1:9
|
1 | #![deny(clippy::implicit_return)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return