How to export rust functions from child module?

I have a rust crate with a few different modules.

I wish to export some of the functions from each module so that they can be called by C programs.

The top-level library module (src/lib.rs) does something like this:

mod foo;

pub use foo::*;

The foo module does this:

pub unsafe extern "C" fn FOO_Init(foovalue: *mut c_ushort) {
    *foovalue = FOO_INIT_VALUE;
}

However, when I build the crate, although it creates the expected shared library (libfoo.so), it doesn't contain the FOO_Init function.

I've discovered that FOO_Init will only be exported if I define it in src/lib.rs, instead of the module source file src/foo.rs. Why?

2 Likes

Did you annotate the function with #[no_mangle]?

1 Like

My understanding was that #[no_mangle] only affected the name mangling of the function, not whether the function would be exported at all. When I do a comparison of 'nm' on the .so file without the function, and then with the function, I see no difference unless I add #[no_mangle]. That doesn't seem right.

With that said, the real problem was that I had this at the top of my src/foo.rs:

#![no_mangle]

...but it doesn't appear to have any effect at all. Instead, I apparently have to decorate each individual function with #[no_mangle] not only to ensure mangling isn't applied, but also to ensure the function is actually exported.

Thanks for the quick response though, but it looks like I have a few bugs to file (although it looks as though there are many against #[no_mangle] already).

1 Like

If you're exporting via the cdylib crate type I believe it must be marked no mangle to be exported.

Also BTW, something like objdump -T is usually more accurate than nm for reporting an "exported symbol" in an elf binary (e.g. symbols the dynamic linker can see)

You can also try out https://GitHub.com/m4b/bingrep too :slight_smile:

1 Like

Yes, you have to add #[no_mangle] in front of every single function that you want to be "seen" by C, and it's a magical attribute that ignores Rust's own rules for function visibility. I think that's a wart in the language.

1 Like

Did you find a solution? Any functions in submodules that I export is undefined while the ones in lib.rs can be accessed from C... Mangle or pub use, etc, makes no difference.

I already provided what worked for me; I suspect you have a different problem.

You could re-export those symbols from lib.rs as a workaround but I suspect the real answer is that those sub modules are not considered part of the cdylib you’re building.