How to "extern" a function in multiple modules with the same name? - rust

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?

Related

How to call function from Rust naked function?

just started learning Rust. How do you manage a function call from a Rust naked function? Normally,
pub extern "C" fn bar() {
hprintln!("Function Call!");
}
pub extern "C" fn foo() {
unsafe {
asm!(
"blx {}",
...
in(reg) bar as u32,
);
}
}
But foo() being a naked call, I cannot use a register to pass values. There aren't much documentation on this feature and only thing I figured is that I can use constant and symbol, but I'm not sure how they are used. Any useful documentation on this feature or usage guideline would be greatly appreciated! Thanks.
Figured out a quick fix: function parameters are stored in registers (r0-r3).
pub extern "C" fn bar() {
hprintln!("Function Call!");
}
#[naked]
pub extern "C" fn foo(ft: u32) {
unsafe {
asm!(
"blx r0", // ft is stored in r0
);
}
}
// somewhere
foo(bar as u32);
I believe there are different ways to solve this using constant and symbol though. Would appreciate any input.

Rust tells me that an import is unused, and then in the very same breath tells me that I should make that import

Here's the code:
use crate::rooms::room::RoomInterface;
pub mod dogroom {
pub struct R;
impl RoomInterface for R {
}
}
Here's /rooms/mod.rs:
pub mod room {
// Irrelevant stuff
pub trait RoomInterface {
// stuff
}
// stuff
}
Here's what it tells me:
I find it quite arcane that I import the very same thing it wants me to import, and yet it doesn't work.
I've tried pretty much all the permutations of the use keyword, and I can't make it work. What's going on?
uses are scoped to the module that imports them, not the file they are in.
Move the import into the dogroom module:
pub mod dogroom {
use crate::rooms::room::RoomInterface;
pub struct R;
impl RoomInterface for R {
}
}
Alternatively, you might want the dogroom module to reuse everything from the parent module:
use crate::rooms::room::RoomInterface;
pub mod dogroom {
use super::*;
pub struct R;
impl RoomInterface for R {
}
}

Rust Submodule Behavior with Wildcard Use Declarations

I was trying to understand how (sub)module imports work when using wildcard paths. The simplest demonstration I could come up with is as follows, where two modules, or perhaps two crates, share the same module structure.
pub mod primary {
pub mod a {
pub mod b {
pub struct A(pub i32);
}
}
}
pub mod import {
pub use crate::primary::*;
// Compiles and executes fine with this commented out, but fails with
// "error[E0433]: failed to resolve: could not find `b` in `a`"
// otherwise. The error refers to the usage in the assert_eq macro
// pub mod a {}
}
fn main() {
assert_eq!(import::a::b::A(42).0, 42);
}
My general thought, was, since the first case, where the pub mod a {} is commented out works, the wildcard should expand all submodules the wildcard picks up into submodules in the path in which it is expanding. Is this not the case? If so, what's the appropriate way to think about?
The Use declarations doesn't have a lot of detail on this.
use with a * imports all the names, except for those that would conflict with names that already exist in the current module.
Compare:
pub mod primary {
pub fn f() {
println!("p::f");
}
}
pub mod import {
pub use crate::primary::*;
}
fn main() {
import::f();
}
which prints p::f to
pub mod primary {
pub fn f() {
println!("p::f");
}
}
pub mod import {
pub use crate::primary::*;
pub fn f() {
println!("import::f");
}
}
fn main() {
import::f();
}
which prints import::f.
This might seem obvious for functions and constants (it would otherwise make * very limited, making it impossible for upstream libraries to add any item without risking to break downstream users), but it might seem more confusing for modules.
You have to remember though that you can't define a module multiple times (ie. "reopen" a module). The following is illegal:
pub mod primary {
pub mod a {}
pub mod a {}
}
and fails with
error[E0428]: the name `a` is defined multiple times
--> src/lib.rs:3:5
|
2 | pub mod a {}
| --------- previous definition of the module `a` here
3 | pub mod a {}
| ^^^^^^^^^ `a` redefined here
|
= note: `a` must be defined only once in the type namespace of this module
You can solve this particular case by adding one more level:
pub mod primary {
pub mod a {
pub mod b {
pub struct A(pub i32);
}
}
}
pub mod import {
pub mod a {
pub use crate::primary::a::*;
}
}
fn main() {
assert_eq!(import::a::b::A(42).0, 42);
}
A wildcard import creates aliases to all items on the top level of the module.
In your example, since primary contains only one item, a, the wildcard import creates an alias import::a, which refers to the module primary::a.
Whenever conflicts arise, explicitly named items are given higher precedence than items that were imported via a wildcard. Effectively, you can shadow a wildcard import by declaring a new item or by importing it by name from another module.
Each mod declaration declares a different module. There is no implicit merging of items in modules that happen to have the same name or alias.

When if ever do pub and pub(super) have different semantics?

Rust has support for both pub and pub(super). pub makes it so the parent module can access an item... and pub(super) seems to also do exactly the same thing. I've tried playing with the example below, and swapping pub and pub(super) seems to have no effect:
#![allow(dead_code)]
mod outer {
pub(super) fn outer_foo() { inner::inner_foo(); }
mod inner {
pub(super) fn inner_foo() { println!("hello world!"); }
}
}
fn top_level_foo() { outer::outer_foo(); }
Why would you ever use one over the other?
Playground link.
In your example, if you change your inner module to be public, then the difference would become clear.
For example, this works because outer::inner::inner_foo is visible from the main module:
#![allow(dead_code)]
mod outer {
pub(super) fn outer_foo() { inner::inner_foo(); }
pub mod inner {
pub fn inner_foo() { println!("hello world!"); }
}
}
fn top_level_foo() { outer::outer_foo(); }
fn main() {
outer::inner::inner_foo();
}
If you kept inner_foo as pub(super) it would've been only visible from the outer module (because super refers to the super-module, outer in the case of something inside inner), hence the above code wouldn't compile and you would see this error:
|
13 | outer::inner::inner_foo();
| ^^^^^^^^^ private function
|
note: the function `inner_foo` is defined here
Notice that pub can also take crate as an argument, making the function public within the crate itself, but not to other crates.

Storing a module as a variable in rust

I have 2 different modules with precisely the same implementation, same functions, types, etc. They just do different things. I would like to be able to choose one of these modules at runtime and use it exclusively. Furthermore, there are several of these modules that may or may not exist at compile-time based on platform, features, etc. this is a link to a super stripped-down version of what I want. I am trying to choose between the various gfx-hal backends. The best I have been able to come up with is a macro that creates an if statement for each possible module then fires that if statement whenever a function in a module is run. However, this doesn't really seem elegant or at all good. So is there a way to store the modules in a variable and access it, or some way to do this that mimics that?
Thanks in advance
You could do this by turning each of your modules into its own trait implementation, similar to how gfx-rs does things.
Your "trait" would in actuality never be implemented with state, and instead be a collection of associated items like functions, other types, etc.
You could package it up like so:
#![allow(dead_code)]
mod foo {
pub fn print() { println!("hello from foo") }
}
mod bar {
pub fn print() { println!("hello from bar"); }
}
mod zam { // this may not exist depending on the platform, one will always exist
pub fn print() { println!("hello from zam"); }
}
struct FOO;
struct BAR;
struct ZAM;
trait RuntimeModule {
fn print();
}
impl RuntimeModule for FOO {
fn print() { foo::print(); }
}
impl RuntimeModule for BAR {
fn print() { bar::print(); }
}
impl RuntimeModule for ZAM {
fn print() { zam::print(); }
}
fn main() {
// Here we decide which to use
print_module::<FOO>();
}
// This is our "entrypoint"
fn print_module<T: RuntimeModule>() {
T::print();
}
If we decide which to use at runtime (in this case in main), we can then call a generic function which will use the associated types/functions to make decisions.
Note that you would not be able to use Box<dyn RuntimeModule> if RuntimeModule contained associated types that were different for each implementation.

Resources