3

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Andrew Mackenzie
  • 5,477
  • 5
  • 48
  • 70
  • 2
    But then when you call `run` from the web assembly, which function should get called? – Jmb Jan 31 '19 at 09:22
  • Not an answer to your question, but do you know about `wasm-bindgen`? That seems to be the de-facto solution for WASM stuff right now. – Lukas Kalbertodt Jan 31 '19 at 09:43

1 Answers1

5

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:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Thanks. Just to be 100% clear. It's the "extern" keyword that effectively takes the fn name from within a module and makes it available in the global namespace? – Andrew Mackenzie Jan 31 '19 at 19:08
  • 3
    @AndrewMackenzie no, it's `no_mangle`: "do not mangle this function name so that it's (very likely to be) unique in the global namespace, I will handle it." – Shepmaster Jan 31 '19 at 19:18