I'm building out a crate and for use across several applications I'm working on. At the moment, I have a handful of functions that serve as 'helpers' for the rest of the crate which I would like to expose across my crate but not to the applications. Is there a way to do this? A middle ground between public and private?
example:
// lib.rs
pub mod mod_a;
pub mod mod_b;
// mod_a.rs, mod_b.rs
use helpers::bar;
pub fn foo() {
bar()
}
...
// helpers.rs
pub fn bar(x: i64) {
return(x+1)
}
I would like to expose the function bar to mod_a and mod_b, without exporting it from my crate
Use pub(crate) while declaring items.
Related
I must admit, I am having a hard time making sense of the Rust compiler error messages.
I have this module:
src/adapters.js
use actix_web::{Responder, HttpResponse};
pub mod Basic {
pub fn api_index() -> &'static str {
"API"
}
pub fn admin_index() -> impl Responder {
HttpResponse::Ok().body("hello world!")
}
}
The Rust compiler keeps telling me when I use
use crate::actix_web::{Responder, HttpResponse};
that:
E0432: unresolved import `crate::actix_web` maybe a missing crate `actix_web`?
Rest assured, crate::actix_web is not missing, because I can run simple requests from main.rs. The problem starts when I want to use the actix_web modules within my own modules.
If I have
use actix_web::{Responder, HttpResponse};
Rust keeps teeling me:
error[E0433]: failed to resolve: use of undeclared type or module `HttpResponse`
HttpResponse::Ok().body("hello world!")
^^^^^^^^^^^^ not found in this scope
help: consider importing one of these items
use actix_web::HttpResponse;
use crate::adapters::HttpResponse;
E0432: unresolved import `crate::actix_web` maybe a missing crate `actix_web`?
I my main.rs, as the first line, I've also declared:
extern crate actix_web;
For the sake of making sure, I've also added "extern crate actix_web;" to the adapters.rs module right at the start. That didn't change anything either.
I am running out of options, I don't know what else I could possibly do.
Basically You have created one another module Basic inside adapters module.So Basic is submodule of adapters module. So two ways you can access the external crate in this case.
Import external crate modules inside your Basic Module.
pub mod Basic {
use actix_web::{Responder, HttpResponse};
pub fn api_index() -> &'static str {
"API"
}
pub fn admin_index() -> impl Responder {
HttpResponse::Ok().body("hello world!")
}
}
Or import an external module in outer module module and access those module using use super keyword in inner module.
use actix_web::{Responder, HttpResponse};
pub mod Basic {
pub fn api_index() -> &'static str {
"API"
}
pub fn admin_index() -> impl super::Responder {
super::HttpResponse::Ok().body("hello world!")
}
}
I have a lib project with multiple modules called one and two, in separate files. Each module has a function called run:
mod one {
pub fn run() {
println!("One");
}
}
mod two {
pub fn run() {
println!("Two");
}
}
fn main() {
one::run();
two::run();
}
Playground
I would like to compile each of these files/functions to WebAssembly and then be able to load them and call the function run().
I believe I have to add the #[no_mangle] directive and mark them as extern "C" functions. When I do that, then there is a name clash on the run function, despite the module structure.
This is the modified version that won't compile:
mod one {
#[no_mangle]
pub extern "C" fn run() {
println!("One");
}
}
mod two {
#[no_mangle]
pub extern "C" fn run() {
println!("Two");
}
}
fn main() {
one::run();
two::run();
}
Playground
Is there a way to have multiple modules in a project, each with a function with the same name, such that I can compile the files with the function to WebAssembly, preserving the function name?
No, you cannot give multiple things the same name in a global namespace. That's kind of the definition of what a name and a namespace is. You will need to export them as two different names.
I prefer to have a single location that exports things so it's easier to see and prevent clashes. Additionally, your symbols should be unique among all libraries that will ever be linked with your library. That's why most high-quality C projects use the library name in every single public method.
mod one {
pub fn run() {
println!("One");
}
}
mod two {
pub fn run() {
println!("Two");
}
}
#[no_mangle]
pub extern "C" fn mylib_one_run() {
one::run()
}
#[no_mangle]
pub extern "C" fn mylib_two_run() {
two::run()
}
fn main() {
one::run();
two::run();
}
See also:
How do I apply a macro attribute to a function defined in a separate module?
I have many Rust functions working perfectly across Ruby FFI. But following directions from two different sites for creating a free_array method is not making the method available in the linked library.
This example is the working example of freeing a String returned from Ruby.
use libc::c_char;
use std::ffi::CString;
#[no_mangle]
pub extern "C" fn free_string(s: *mut c_char) {
unsafe {
if s.is_null() { return }
CString::from_raw(s)
};
}
And here are two attempts at implementing a way to free the memory of an Array.
use std::mem::transmute;
use ruby_array::RubyArray;
#[no_mangle]
pub extern "C" fn free_array(ra: *mut RubyArray) {
let _ra: Box<RubyArray> = unsafe{ transmute(ra) };
}
// OR
#[no_mangle]
pub extern "C" fn free_array(ptr: *mut RubyArray) {
if ptr.is_null() { return }
unsafe { Box::from_raw(ptr); }
}
This results in an error:
Function 'free_array' not found in [/libfaster_path.so] (FFI::NotFoundError)
Here's the Struct I'm using and which gets created perfectly in to Ruby from Rust.
use libc;
use std::mem;
#[repr(C)]
pub struct RubyArray {
len: libc::size_t,
data: *const libc::c_void,
}
impl RubyArray {
#[allow(dead_code)]
pub fn from_vec<T>(vec: Vec<T>) -> RubyArray {
let array = RubyArray {
data: vec.as_ptr() as *const libc::c_void,
len: vec.len() as libc::size_t
};
mem::forget(vec);
array
}
}
But that's not relevant as it's not the issue. The issue is the method is not being made available in the library output for FFI to read from. What's wrong with this? Rust is happy and I've written many other methods in similar manner that work. What makes this not found in the .so file?
The file is included in the main src/lib.rs with pub mod so there's nothing wrong there. It's the same as the other working methods.
I'll be posting a blog with much fuller implementation details later and I'll add a link to the comment section below for those who are interested.
Minor Update
I'm pretty sure this is an issue with Rust. I've used both Ruby's Fiddle and FFI to verify that this method couldn't be accessed where as other methods could be by both.
I grepped the binary and found the text showing the free_array method in the binary but apparently that's not compiled correctly to be read by FFI.
The information I provided was not enough to debug the issue. The real problem was I had changed from building source from release to debug and had not updated the FFI linked library folder to reflect that. So the code kept pointing at and old lib.
If you have a directory structure like this:
src/main.rs
src/module1/blah.rs
src/module1/blah2.rs
src/utils/logging.rs
How do you use functions from other files?
From the Rust tutorial, it sounds like I should be able to do this:
main.rs
mod utils { pub mod logging; }
mod module1 { pub mod blah; }
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}
logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
blah.rs
mod blah2;
pub fn doit() {
blah2::doit();
}
blah2.rs
mod utils { pub mod logging; }
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}
However, this produces an error:
error[E0583]: file not found for module `logging`
--> src/main.rs:1:21
|
1 | mod utils { pub mod logging; }
| ^^^^^^^
|
= help: name the file either logging.rs or logging/mod.rs inside the directory "src/utils"
It appears that importing down the path, i.e. from main to module1/blah.rs works, and importing peers, i.e. blah2 from blah works, but importing from the parent scope doesn't.
If I use the magical #[path] directive, I can make this work:
blah2.rs
#[path="../utils/logging.rs"]
mod logging;
pub fn doit() {
logging::trace("Blah2 invoked");
}
Do I really have to manually use relative file paths to import something from a parent scope level? Isn't there some better way of doing this in Rust?
In Python, you use from .blah import x for the local scope, but if you want to access an absolute path you can use from project.namespace.blah import x.
I'm going to answer this question too, for anyone else who finds this and is (like me) totally confused by the difficult-to-comprehend answers.
It boils down to two things I feel are poorly explained in the tutorial:
The mod blah; syntax imports a file for the compiler. You must use this on all the files you want to compile.
As well as shared libraries, any local module that is defined can be imported into the current scope using use blah::blah;.
A typical example would be:
src/main.rs
src/one/one.rs
src/two/two.rs
In this case, you can have code in one.rs from two.rs by using use:
use two::two; // <-- Imports two::two into the local scope as 'two::'
pub fn bar() {
println!("one");
two::foo();
}
However, main.rs will have to be something like:
use one::one::bar; // <-- Use one::one::bar
mod one { pub mod one; } // <-- Awkwardly import one.rs as a file to compile.
// Notice how we have to awkwardly import two/two.rs even though we don't
// actually use it in this file; if we don't, then the compiler will never
// load it, and one/one.rs will be unable to resolve two::two.
mod two { pub mod two; }
fn main() {
bar();
}
Notice that you can use the blah/mod.rs file to somewhat alleviate the awkwardness, by placing a file like one/mod.rs, because mod x; attempts x.rs and x/mod.rs as loads.
// one/mod.rs
pub mod one.rs
You can reduce the awkward file imports at the top of main.rs to:
use one::one::bar;
mod one; // <-- Loads one/mod.rs, which loads one/one.rs.
mod two; // <-- This is still awkward since we don't two, but unavoidable.
fn main() {
bar();
}
There's an example project doing this on Github.
It's worth noting that modules are independent of the files the code blocks are contained in; although it would appear the only way to load a file blah.rs is to create a module called blah, you can use the #[path] to get around this, if you need to for some reason. Unfortunately, it doesn't appear to support wildcards, aggregating functions from multiple files into a top-level module is rather tedious.
I'm assuming you want to declare utils and utils::logging at the top level, and just wish to call functions from them inside module1::blah::blah2. The declaration of a module is done with mod, which inserts it into the AST and defines its canonical foo::bar::baz-style path, and normal interactions with a module (away from the declaration) are done with use.
// main.rs
mod utils {
pub mod logging { // could be placed in utils/logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
}
}
mod module1 {
pub mod blah { // in module1/blah.rs
mod blah2 { // in module1/blah2.rs
// *** this line is the key, to bring utils into scope ***
use crate::utils;
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}
}
pub fn doit() {
blah2::doit();
}
}
}
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}
The only change I made was the use crate::utils; line in blah2 (in Rust 2015 you could also use use utils or use ::utils). Also see the second half of this answer for more details on how use works. The relevant section of The Rust Programming Language is a reasonable reference too, in particular these two subsections:
Separating Modules into Different Files
Bringing Paths into Scope with the use Keyword
Also, notice that I write it all inline, placing the contents of foo/bar.rs in mod foo { mod bar { <contents> } } directly, changing this to mod foo { mod bar; } with the relevant file available should be identical.
(By the way, println(": {}\n", msg) prints two new lines; println! includes one already (the ln is "line"), either print!(": {}\n", msg) or println!(": {}", msg) print only one.)
It's not idiomatic to get the exact structure you want, you have to make one change to the location of blah2.rs:
src
├── main.rs
├── module1
│ ├── blah
│ │ └── blah2.rs
│ └── blah.rs
└── utils
└── logging.rs
main.rs
mod utils {
pub mod logging;
}
mod module1 {
pub mod blah;
}
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}
utils/logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
module1/blah.rs
mod blah2;
pub fn doit() {
blah2::doit();
}
module1/blah/blah2.rs (the only file that requires any changes)
// this is the only change
// Rust 2015
// use utils;
// Rust 2018
use crate::utils;
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}
I realize this is a very old post and probably wasn't using 2018. However, this can still be really tricky and I wanted to help those out that were looking.
Because Pictures are worth a thousand words I made this simple for code splitting.
Then as you probably guessed they all have an empty pub fn some_function().
We can further expand on this via the changes to main
The additional changes to nested_mod
Let's now go back and answer the question:
We added blah1 and blah2 to the mod_1
We added a utils with another mod logging inside it that calls some fn's.
Our mod_1/mod.rs now contains:
pub mod blah.rs
pub mod blah2.rs
We created a utils/mod.rs used in main containing:
pub mod logging
Then a directory called logging/with another mod.rs where we can put fns in logging to import.
Source also here https://github.com/DavidWhit/Rust_Modules
Also Check Chapters 7 for libs example and 14.3 that further expands splitting with workspaces in the Rust Book. Good Luck!
Answers here were unclear for me so I will put my two cents for future Rustaceans.
All you need to do is to declare all files via mod in src/main.rs (and fn main of course).
// src/main.rs
mod module1 {
pub mod blah;
pub mod blah2;
}
mod utils {
pub mod logging;
}
fn main () {
module1::blah::doit();
}
Make everything public with pub you need to use externally (copy-pasted original src/utils/logging.rs). And then simply use declared modules via crate::.
// src/module1/blah.rs
use crate::utils::logging;
// or `use crate::utils` and `utils::logging::("log")`, however you like
pub fn doit() {
logging::trace("Logging works");
}
p.s. I shuffled functions a bit for a cleaner answer.
If you create a file called mod.rs, rustc will look at it when importing a module. I would suggest that you create the file src/utils/mod.rs, and make its contents look something like this:
pub mod logging;
Then, in main.rs, add a statement like this:
use utils::logging;
and call it with
logging::trace(...);
or you could do
use utils::logging::trace;
...
trace(...);
Basically, declare your module in the mod.rs file, and use it in your source files.
I am writing a wrapper/FFI for a C library that requires a global initialization call in the main thread as well as one for destruction.
Here is how I am currently handling it:
struct App;
impl App {
fn init() -> Self {
unsafe { ffi::InitializeMyCLib(); }
App
}
}
impl Drop for App {
fn drop(&mut self) {
unsafe { ffi::DestroyMyCLib(); }
}
}
which can be used like:
fn main() {
let _init_ = App::init();
// ...
}
This works fine, but it feels like a hack, tying these calls to the lifetime of an unnecessary struct. Having the destructor in a finally (Java) or at_exit (Ruby) block seems theoretically more appropriate.
Is there some more graceful way to do this in Rust?
EDIT
Would it be possible/safe to use this setup like so (using the lazy_static crate), instead of my second block above:
lazy_static! {
static ref APP: App = App::new();
}
Would this reference be guaranteed to be initialized before any other code and destroyed on exit? Is it bad practice to use lazy_static in a library?
This would also make it easier to facilitate access to the FFI through this one struct, since I wouldn't have to bother passing around the reference to the instantiated struct (called _init_ in my original example).
This would also make it safer in some ways, since I could make the App struct default constructor private.
I know of no way of enforcing that a method be called in the main thread beyond strongly-worded documentation. So, ignoring that requirement... :-)
Generally, I'd use std::sync::Once, which seems basically designed for this case:
A synchronization primitive which can be used to run a one-time global
initialization. Useful for one-time initialization for FFI or related
functionality. This type can only be constructed with the ONCE_INIT
value.
Note that there's no provision for any cleanup; many times you just have to leak whatever the library has done. Usually if a library has a dedicated cleanup path, it has also been structured to store all that initialized data in a type that is then passed into subsequent functions as some kind of context or environment. This would map nicely to Rust types.
Warning
Your current code is not as protective as you hope it is. Since your App is an empty struct, an end-user can construct it without calling your method:
let _init_ = App;
We will use a zero-sized argument to prevent this. See also What's the Rust idiom to define a field pointing to a C opaque pointer? for the proper way to construct opaque types for FFI.
Altogether, I'd use something like this:
use std::sync::Once;
mod ffi {
extern "C" {
pub fn InitializeMyCLib();
pub fn CoolMethod(arg: u8);
}
}
static C_LIB_INITIALIZED: Once = Once::new();
#[derive(Copy, Clone)]
struct TheLibrary(());
impl TheLibrary {
fn new() -> Self {
C_LIB_INITIALIZED.call_once(|| unsafe {
ffi::InitializeMyCLib();
});
TheLibrary(())
}
fn cool_method(&self, arg: u8) {
unsafe { ffi::CoolMethod(arg) }
}
}
fn main() {
let lib = TheLibrary::new();
lib.cool_method(42);
}
I did some digging around to see how other FFI libs handle this situation. Here is what I am currently using (similar to #Shepmaster's answer and based loosely on the initialization routine of curl-rust):
fn initialize() {
static INIT: Once = ONCE_INIT;
INIT.call_once(|| unsafe {
ffi::InitializeMyCLib();
assert_eq!(libc::atexit(cleanup), 0);
});
extern fn cleanup() {
unsafe { ffi::DestroyMyCLib(); }
}
}
I then call this function inside the public constructors for my public structs.