Rust unresolved import no `size_t` in the root - rust

I've got a project that builds for ios, android and wasm targets, when I build for ios and android everything works but when I build for wasm I get the following error;
Im unsure what this error message actually means, I'm using an external crate libc, here's the code from my src/string.rs file
use libc::size_t;
// Helper struct that is used to give strings to C.
#[repr(C)]
pub struct StringPtr {
pub ptr: *const u8,
pub len: size_t,
}
impl<'a> From<&'a str> for StringPtr {
fn from(s: &'a str) -> Self {
StringPtr {
ptr: s.as_ptr(),
len: s.len() as size_t,
}
}
}
impl StringPtr {
pub fn as_str(&self) -> &str {
use std::{slice, str};
unsafe {
let slice = slice::from_raw_parts(self.ptr, self.len);
str::from_utf8(slice).unwrap()
}
}
}
and inside my lib.rs file I've got the following to import my string.rs file
extern crate libc;
mod string;
use string::StringPtr;
It's also worth noting that I am using cfg to conditionally include different code for different targets, maybe this is part of the problem?

Related

Rust to Rust FFI plugin system segfault when in struct

I am trying to create simple Rust-to-Rust plugin system using DLLs and I am mostly following this guide: https://michael-f-bryan.github.io/rust-ffi-guide/dynamic_loading.html
However after I load my .dll/.so file using libloading it works perfectly when I use the library as is, however when I put it into a struct with, it causes SIGSEGV on drop.
Plugin minimal example code:
pub trait Plugin{
fn new() -> Self where Self: Sized;
fn get_data(&self) -> Data;
}
pub struct Data {
pub string: String
}
#[derive(Debug, Clone)]
struct MyPlugin;
impl Plugin for MyPlugin {
fn new() -> Self {
MyPlugin {}
}
fn get_data(&self) -> Data {
Data { string: "Hello, world!".to_string() }
}
}
#[no_mangle]
pub extern "C" fn _create_plugin() -> *mut dyn Plugin {
Box::into_raw(Box::new(MyPlugin::new()))
}
App minimal example code:
use std::error::Error;
use libloading::{Library, Symbol};
use plugin::Plugin;
fn main() {
load().expect("Failed");
}
fn load() -> Result<(), Box<dyn Error>> {
let plugin = unsafe {
#[cfg(unix)]
let file = "target/debug/libplugin.so";
#[cfg(windows)]
let file = "target/debug/plugin.dll";
let lib = Library::new(file)?;
let constructor: Symbol<unsafe fn() -> *mut dyn Plugin> = lib.get(b"_create_plugin")?;
let plugin = Box::from_raw(constructor());
PluginWrapper::new(lib, plugin)
};
println!("{}", plugin.plugin.get_data().string);
Ok(())
}
struct PluginWrapper {
library: Library,
pub plugin: Box<dyn Plugin>
}
impl PluginWrapper {
pub fn new(library: Library, plugin: Box<dyn Plugin>) -> PluginWrapper {
PluginWrapper { library, plugin }
}
}
Causes segmentation fault, backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x000055555555fb48 in core::ptr::drop_in_place<alloc::boxed::Box<dyn plugin::Plugin, alloc::alloc::Global>> () at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ptr/mod.rs:188
188 /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ptr/mod.rs: No such file or directory.
(gdb) bt
#0 0x000055555555fb48 in core::ptr::drop_in_place<alloc::boxed::Box<dyn plugin::Plugin, alloc::alloc::Global>> ()
at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ptr/mod.rs:188
#1 0x000055555555de54 in core::ptr::drop_in_place<app::PluginWrapper> ()
at /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ptr/mod.rs:188
#2 0x000055555555f1d2 in app::load () at app/src/main.rs:24
#3 0x000055555555ed79 in app::main () at app/src/main.rs:6
I also have bigger example, where I can reproduce the SIGSEGV on Windows, but not on Linux, however I do believe it's related and I am doing some fundamental mistake. Can someone point me in the right direction what I am doing wrong? Thank you.

try_into() is breaking when used on u8

So I don't have a lot of knowledge on this script, compiling as part of a larger project for ARM. This comes from the zksync library which is designed primarily for x86.
I keep running into a conversion error when compiling:
7 | .try_into()
| ^^^^^^^^ the trait `std::convert::From<std::vec::Vec<u8>>` is not implemented for `[u8; 16]`
I tried using try_from() as many of my searches recommended but wasn't able to get it running, as I am still very new to rust, but open to if anyone can get it working.
I am compiling with the following target and linker below -
target - arm-unknown-linux-musleabi
linker - arm-linux-gnueabihf-ld
If anyone can recommend how to to fix this I'd love to hear, I was thinking usize instead of the u64 vars, but couldn't quite figure out if that is the rabbit hole I should try going down.
Full code:
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
/// Defines time range `[valid_from, valid_until]` for which transaction is valid,
/// time format is the same as Ethereum (UNIX timestamp in seconds)
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TimeRange {
pub valid_from: u64,
pub valid_until: u64,
}
impl TimeRange {
pub fn new(valid_from: u64, valid_until: u64) -> Self {
Self {
valid_from,
valid_until,
}
}
pub fn to_be_bytes(&self) -> [u8; 16] {
[
self.valid_from.to_be_bytes(),
self.valid_until.to_be_bytes(),
]
.concat()
.try_into()
.expect("valid_from and valid_until should be u64")
}
pub fn check_correctness(&self) -> bool {
self.valid_from <= self.valid_until
}
pub fn is_valid(&self, block_timestamp: u64) -> bool {
self.valid_from <= block_timestamp && block_timestamp <= self.valid_until
}
}
impl Default for TimeRange {
fn default() -> Self {
Self {
valid_from: 0,
valid_until: u64::max_value(),
}
}
}
Your code compiles successfully on the current stable release (v1.51).
However, TryFrom<Vec<_>> for slices (which is what allows you to use try_into()) was only added in rust 1.48, so maybe you are running a rust version older that 1.48. If so, updating to 1.48+ should fix your problem.

Two similar code snippets but only one triggers a lifetime error

#![feature(rustc_private)]
extern crate rustc;
use rustc::hir::intravisit as hir_visit;
use rustc::hir;
use std::marker::PhantomData;
// ----------------------------------------------------------------------------
// Why does this compile?
// ----------------------------------------------------------------------------
pub struct Map<'a> {
pub _m: PhantomData<&'a ()>,
}
pub struct SomeVisitor<'a, 'tcx: 'a> {
pub map: &'a Map<'tcx>,
}
pub enum NestedVisitorMap<'this, 'tcx: 'this> {
None,
OnlyBodies(&'this Map<'tcx>),
All(&'this Map<'tcx>),
}
pub trait Visitor<'v>: Sized {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v>;
}
impl<'v, 'tcx> Visitor<'v> for SomeVisitor<'v, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
NestedVisitorMap::All(self.map)
}
}
// ----------------------------------------------------------------------------
// Why does this *not* compile?
// ----------------------------------------------------------------------------
pub struct SomeVisitor2<'a, 'tcx: 'a> {
pub map: &'a hir::map::Map<'tcx>,
}
impl<'v, 'tcx> hir_visit::Visitor<'v> for SomeVisitor2<'v, 'tcx> {
fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> {
hir_visit::NestedVisitorMap::All(self.map)
}
}
fn main() {}
playground
NestedVisitorMap and Visitor
I recently ran into a lifetime issue and I decided to recreate it without any dependencies. The odd thing is that I can not recreate the lifetime error. To me both implementations look the same from the outside, but only one compiles successfully. Why is that?
rustc 1.21.0-nightly (e26688824 2017-08-27)
Update:
The problem seems to be the RefCell inside Map.
#[derive(Clone)]
pub struct Map<'hir> {
inlined_bodies: RefCell<rustc::util::nodemap::DefIdMap<&'hir hir::Body>>,
}
If there is a RefCell with a inner lifetime, it will trigger an error.
playground
Update2:
It turns out that I just mixed up lifetime subtyping. playground
I still don't know why only RefCell causes the error.

Source trait is inaccessible

The situation is (severely simplified) this (playpen):
mod tokentree {
pub struct TokenTree;
mod serialize {
use std::collections::BTreeMap;
use super::TokenTree;
#[derive(Debug)]
pub struct InternStr;
pub trait InternStrsExt {
fn intern_strs(&self) -> BTreeMap<&str, InternStr>;
}
impl InternStrsExt for [TokenTree] {
fn intern_strs(&self) -> BTreeMap<&str, InternStr> { BTreeMap::new() }
}
}
pub use self::serialize::{InternStrsExt, InternStr};
}
use tokentree::*;
fn main() {
println!("{:?}", [TokenTree].intern_strs());
}
I get the following error (both on nightly and beta):
<anon>:20:22: 20:47 error: source trait is inaccessible
<anon>:20 println!("{:?}", [TokenTree].intern_strs());
^~~~~~~~~~~~~~~~~~~~~~~~~
My problem is that I don't even know what this is supposed to mean.
It needs a pub declaration. Also your declarations are all over the place. Recommended form is to stick your pub mod declarations first, then, use.
Here is the working example.
mod tokentree {
pub struct TokenTree;
pub mod serialize {
use std::collections::BTreeMap;
use super::TokenTree;
#[derive(Debug)]
pub struct InternStr;
pub trait InternStrsExt {
fn intern_strs(&self) -> BTreeMap<&str, InternStr>;
}
impl InternStrsExt for [TokenTree] {
fn intern_strs(&self) -> BTreeMap<&str, InternStr> { BTreeMap::new() }
}
}
pub use self::serialize::{InternStrsExt, InternStr};
}
pub use tokentree::*;
fn main() {
println!("{:?}", [TokenTree].intern_strs());
}
(playpen)
What happened here is that you stumbled upon following glitches:
https://github.com/rust-lang/rust/issues/18241
https://github.com/rust-lang/rust/issues/16264
You can't export your traits from a private module. That's why you need to change mod serialize into pub mod serialize. For example this playpen example demonstrates that exporting struct Export works, but un-commenting the println! will make it stop compiling, because we used a trait.
Tip: One thing that helps me with the visibility rules is to generate doc files and see which doc files are visible.

How to access Rust from other languages

Previously when the code-base was in C++, I had C++ wrapper files which would link to the code base and I would run swig (version 3 for C++11 support) to generate the interface files for the target language (Python, JavaScript, C#, etc.). Then of course get all these files and libraries compiled into a shared object and have it invoked from the required languages. Now the code base is being changed to rust. So for swig to work I have the following:
Main rust code file compiling into an rlib.
Rust wrapper file that calls into the main code base but uses no_mangle and extern syntax for FFI and compiles into a staticlib.
A C file that calls the rust wrapper and is a replica of it.
Now I use swig on the C file, get the interface file for the target language, combine all the files (steps two and three) and the SWIG interface file) into a shared object and call from the target language.
So:
Is the approach fine?
I can get free functions to work. However I'm confused on how to get member functions (methods) to work. In C++ the first parameter of the member functions is the implicit this pointer. So I could return a void* handle to the class or struct to the C interface which would pass it on to others who wanted to store it (e.g. jsctypes for Firefox) and then on receiving again reinterpret_cast it to the concrete/actual type and invoke the member function on it. How do I do this with Rust?
e.g., for
pub struct A { id: SomeType, }
impl A {
pub fn some_funct_0(&mut self) {}
pub fn some_funct_1(&self) {}
}
impl SomeTrait for A {
fn some_trait_funct(&mut self) {}
}
So how do I access these member functions on an object of A (should be unmanaged and on the heap I guess?) from target languages (Python, C, etc.) or even simply a C interface?
Well, methods are just regular functions, and as Chris said, self argument has implicit connection with Self type. With your example (slightly modified) using functions from C code should be straightforward:
#[repr(C)]
pub struct A { id: u32, }
#[no_mangle]
pub extern fn new_a(id: u32) -> A {
A { id: id }
}
impl A {
#[no_mangle]
pub extern fn some_funct(&self) {
println!("Called some_funct: {}", self.id);
}
}
trait SomeTrait {
extern fn some_trait_funct(&self);
}
impl SomeTrait for A {
#[no_mangle]
extern fn some_trait_funct(&self) {
println!("Called some_trait_funct: {}", self.id);
}
}
Note that I added extern to change calling convention and #[no_mangle] to avoid name mangling and #[repr(C)] on the struct. The latter is not necessary if your code creates Boxes of the struct and pass them to C as raw pointers. I'm not sure, however, how #[no_mangle] could affect trait methods if there is more than one trait implementor - if both have #[no_mangle], there is bound to be some kind of name conflict.
Now using this type and its functions from C is easy:
#include <stdint.h>
struct A {
uint32_t id;
};
extern struct A new_a(uint32_t id);
extern void some_funct(const struct A *self);
extern void some_trait_funct(const struct A *self);
int main() {
struct A a = new_a(123);
some_funct(&a);
some_trait_funct(&a);
}
This program compiles and works:
% rustc --crate-type=staticlib test.rs
multirust: a new version of 'nightly' is available. run `multirust update nightly` to install it
note: link against the following native artifacts when linking against this static library
note: the order and any duplication can be significant on some platforms, and so may need to be preserved
note: library: System
note: library: pthread
note: library: c
note: library: m
% gcc -o test_use test_use.c libtest.a -lSystem -lpthread -lc -lm
% ./test_use
Called some_funct: 123
Called some_trait_funct: 123
If methods accepted &mut self:
#[no_mangle]
extern fn some_funct_mut(&mut self) { ... }
you would need to omit const:
extern void some_funct_mut(struct A *self);
If methods accepted self:
#[no_mangle]
extern fn some_funct_value(self) { ... }
you would need to pass the structure by value:
extern void some_funct_value(struct A self);
Though if you use the structure through an opaque pointer, calling functions taking it by value may be difficult as C has to know the exact size of the structure. Not that it is that common with opaque pointers, I believe.
Ok, as i commented in the accepted answer that I couldn't use that approach, I ended up doing something like this for other's to comment on:
The backend rust code that gets compiled to rlib:
pub trait TestTrait {
fn trait_func(&mut self) -> i32;
}
pub struct TestStruct {
value: i32,
}
impl TestStruct {
pub fn new(value: i32) -> TestStruct {
TestStruct {
value: value,
}
}
pub fn decrement(&mut self, delta: i32) {
self.value -= delta;
}
}
impl TestTrait for TestStruct {
fn trait_func(&mut self) -> i32 {
self.value += 3;
self.value
}
}
The rust-wrapper over this that links to the above rlib and compiles into staticlib (ie., .a in Linux etc):
#[no_mangle]
pub extern fn free_function_wrapper(value: i32) -> i32 {
rustlib::free_function(value)
}
#[no_mangle]
pub extern fn new_test_struct_wrapper(value: i32) -> *mut libc::c_void {
let obj = rustlib::TestStruct::new(value);
unsafe {
let raw_ptr = libc::malloc(mem::size_of::<rustlib::TestStruct>() as libc::size_t) as *mut rustlib::TestStruct;
ptr::write(&mut *raw_ptr, obj);
raw_ptr as *mut libc::c_void
}
}
#[no_mangle]
pub extern fn test_struct_decrement_wrapper(raw_ptr: *mut libc::c_void, delta: i32) {
unsafe {
mem::transmute::<*mut libc::c_void, &mut rustlib::TestStruct>(raw_ptr).decrement(delta);
}
}
#[no_mangle]
pub extern fn test_struct_trait_function_wrapper(raw_ptr: *mut libc::c_void) -> i32 {
unsafe {
mem::transmute::<*mut libc::c_void, &mut rustlib::TestStruct>(raw_ptr).trait_func()
}
}
The C-wrapper (api.h & api.c) that links to the staticlib above and compiles into a shared object if required:
extern int32_t free_function_wrapper(int32_t value);
extern void* new_test_struct_wrapper(int32_t value);
extern void test_struct_decrement_wrapper(void* ptr, int32_t delta);
extern int32_t test_struct_trait_function_wrapper(void* ptr);
int32_t free_function(int32_t value) {
return free_function_wrapper(value);
}
void* new_test_struct(int32_t value) {
return new_test_struct_wrapper(value);
}
void test_struct_decrement(void* ptr, int32_t value) {
test_struct_decrement_wrapper(ptr, value);
}
int32_t test_struct_trait_function(void* ptr) {
return test_struct_trait_function_wrapper(ptr);
}
Now just run SWIG over the C file (i've posted just the .c file - you can guess the .h over which SWIG will run) for the target language, get an interface_wrap.c generated (default name) by it and compile these source code link, them against the staticlib to get a shared-object.
Eg, for python:
swig -python interface.i
gcc -std=c99 -c -fPIC -Wall -Werror -O2 api.c interface_wrap.c -I/usr/include/python2.7
gcc -shared -o _port_sample.so api.o interface_wrap.o -L./ -lrust_wrapper
Now just call from Python and the whole thing works:
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import port_sample
>>> handle = port_sample.new_test_struct(36)
>>> port_sample.test_struct_decrement(handle, 12)
>>> value = port_sample.test_struct_trait_function(handle)
>>> print value
27
>>> exit()
I hope someone finds this useful and/or can suggest improvements etc. I've also got this thing working and committed to my github repo: https://github.com/ustulation/rust-ffi/tree/master/python-swig-rust

Resources