Home > Enterprise >  Is there a way to export functions in C static library?
Is there a way to export functions in C static library?

Time:11-30

i am testing some C code in Rust, but rust only links to C static libraries on windows.

The problem is that the exported C functions are only exported to a Dynamic Library, and not to a Static one, since I can't use dlls in rust, i can't really link to the library with no exported symbols (if I try to, rust complains about unresolved references).

Some things I tried:

  • Normal linking: these worked for a compilation one time, but I lost it, and since all the other normal ones go wrong.

  • Static lib linked with Dynamic lib: sure, but it did not work, nor did the exported symbols appear in dumpbin /exports, or did the static lib rely on the dynamic lib.

  • Static linked to Object linked to Dynamic: what

Code:

C:

// Note this is compiled with CMake to generate both a DyLib and a Static Lib.

#define EXPORT __declspec (dllexport)

EXPORT int my_func (void) {
    return 3;
}

Rust:

// build.rs:

fn main () {
    println!("cargo:rustc-link-search=native=path/to/my/lib");
}

// lib.rs:

#[cfg (test)]
mod tests;

// No *-sys crate for simplicity
pub mod sys {
    #[link (name = "my_lib")] // since Windows msvc linking is based on static libs, no matter what it is going to search for a static lib anyway...
    extern {
        pub fn my_func () -> i32; // libc::c_int is an alias to i32 on my machine
    }
}

// tests.rs:

use crate::sys;

#[test]
fn my_func_works () {
    assert_eq!(3, unsafe { sys::my_func () });
}

CodePudding user response:

In your build script, you're telling cargo where to look for your library, but you never tell it to actually use the library. You need to add this to your build.rs:

println!("cargo:rustc-link-lib=native=my_lib.lib");

Note that the cargo docs have this to say about rustc-link-search (emphasis mine):

The rustc-link-search instruction tells Cargo to pass the -L flag to the compiler to add a directory to the library search path.

and about rustc-link-lib:

The rustc-link-lib instruction tells Cargo to link the given library using the compiler's -l flag.

CodePudding user response:

It is way out of scope for this answer, but this is why attributes and declspecs are such an anathema to making software work.

If you have a library; that library has some names which have a global scope. For example, you could have a procedure called ShaveMyBall for grooming a football pre-game. In a library, ShaveMyBall might just exist, but you might have some requirements about linking with externals, so that ShaveMyBall might need to be prefixed with MyHairyBits_.

This opposing requirements can readily be solved by symbol manipulation utiities rather than a grotesque infrastructure between programming languages. A few simple object file manipulations can change ShaveMyBall into MyHairyBits_ShaveMyBall.

But, if you insist on using odd, poorly defined, and even worse, partially defined by a standards committe, you will end up with something that may work on occasion, which outside of setting you up for a microsoft buyout, is typically the death knell for any company.

  • Related