How to call the C *.lib static library from Rust?

I wrote a hellolib.lib with Viisual Studio 2013. The code is as follows:

#include <iostream>
void hello(){
	std::cout << "hello!" << std::endl;
}

I wrote another program in C to call it, and it is OK.

I wrote the following code with Rust, but the link failed. Error code is LNK4044. What is the reason?

#[link(name = "hellolib", kind = "static")]
extern "C" {
    pub fn hello();
}

fn main() {
    unsafe{
        hello();
    }
}

BTW, I copied the hellolib.lib to the src folder.

According to documentation, LNK4044 is a warning, not an error. Could you post the full compiler output?

C++ is not C. Even items on the root scope would be name-mangled. To avoid it you need to wrap the function with the extern "C" { } block.

3 Likes

Thank you very much for your reply!
The error message on Windows system is non UTF-8 coded Chinese, which I translated into English, as follows:

link: warning lnk4044: unrecognized option "/ wholearchive: hellolib. Lib";
Ignored link: warning lnk4044:
Unrecognized option "/natvis: C:\users\xuyeping.Rustup\toolchains\stable-x86_ 64-pc-windows-msvc\lib\rustlib\etc\intrinsic.natvis”;
Ignored link: warning lnk4044:
Unrecognized option "/natvis: C:\users\xuyeping.Rustup\toolchains\stable-x86_ 64-pc-windows-msvc\lib\rustlib\etc\liballoc.natvis”;
Ignored link: warning lnk4044:
Unrecognized option "/natvis: C:\users\xuyeping.Rustup\toolchains\stable-x86_ 64-pc-windows-msvc\lib\rustlib\etc\libcore.natvis”;
Ignored link: warning lnk4044:
Unrecognized option "/natvis: C:\users\xuyeping.Rustup\toolchains\stable-x86_ 64-pc-windows-msvc\lib\rustlib\etc\libstd.natvis”;
Ignored callstr.2hcayntbpaw4303q.Rcgu.O: error
LNK2019: unable to resolve the external symbol Hello, which is in the function_ Zn7callstr4main17hea8820bb2316cf0ae referenced
g:... ...\hellocall\target\debug\DEPs\callstr.exe: fatal error lnk1120: 1 unresolved external command

Thanks for your advice!
Unfortunately, after the modification is completed, it still cannot be compiled.

#include <iostream>

extern "C"{
	void hello(){
		std::cout << "hello!" << std::endl;
	}
}

Have you written a build script to tell rustc it needs to link to libhellolib.a and which directories to check when trying to find it?

This worked for me (note I called the library hello because libhellolib.so looks funny):

$ tree .
.
├── build.rs
├── Cargo.toml
├── hello.c
└── src
    └── main.rs

1 directory, 4 files
// hello.c
#include <stdio.h>

void hello() {
    printf("Hello!\n");
}
// src/main.rs
#[link(name = "hello", kind = "static")]
extern "C" {
    pub fn hello();
}

fn main() {
    unsafe {
        hello();
    }
}
// build.rs
fn main() {
    // tell rustc to link with some libhello.a library
    println!("cargo:rustc-link=hello");
    // and it should search the Cargo.toml directory for that library
    println!("cargo:rustc-link-search={}", std::env::var("CARGO_MANIFEST_DIR").unwrap());
}

Then I used this to compile and run:

$ clang -c hello.c -o hello.o
$ ar rc libhello.a hello.o
$ ls
build.rs  Cargo.toml  hello.c  hello.o  libhello.a  src
$ cargo run
   Compiling repro v0.1.0 (/tmp/repro)
    Finished dev [unoptimized + debuginfo] target(s) in 0.16s
     Running `target/debug/repro`
Hello!

Can you specify what "cannot be compiled" means? Are you getting compilation errors from Visual C++, is the linker complaining of missing symbols or unused arguments, etc.?

1 Like

According to your method, the project configuration is as follows:

Processing: [missing %{filename} value]...
image

Cargo.toml

[package]
name = "hellocall"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

build = "build.rs"

[dependencies]

build.rs

fn main() {
    // tell rustc to link with some libhello.a library
    println!("cargo:rustc-link=hello");
    // and it should search the Cargo.toml directory for that library
    println!("cargo:rustc-link-search={}", std::env::var("CARGO_MANIFEST_DIR").unwrap());
}

hello.c

void hello() {}

main.rs

#[link(name = "hello", kind = "static")]
extern "C" {
    pub fn hello();
}

fn main() {
    unsafe{
        hello();
    }
}

I still can't compile. The error message is the same as before. It is still a warning that hello.lib can't be found, and then there is an error that hello can't be found.

I work with VSCode on the Windows 10. This may be different from your compilation environment.

Anyway, thank you very much for your help!

Well, there's indeed no hello.lib in current project structure. How do you compile your hello.c?

As mentioned in the question, initially, I compiled hellolib.lib with Visual Studio 2013. Then copy hellolib.lib to the src folder. The code build.rs is not used. the Rust code main.rs compiled with VSCode. The compilation process prompted that the hellolib.lib file could not be found.

You're telling Rust via build.rs to look in the project root folder, not in src folder.

1 Like

The project root folder has also been tried and cannot be compiled. :frowning_face:

You should compile the project with cargo, which would recognize build.rs.

1 Like

Can Rust call the *.lib static library file generated by the Microsoft Visual C + + Compiler?

With msvc toolchain, yes.

I enter rustup show in the terminal window of VSCode, and the display contents are as follows:

>rustup show
Default host: x86_64-pc-windows-msvc   
rustup home:  C:\Users\...\.rustup

installed toolchains
--------------------

stable-i686-pc-windows-msvc
stable-x86_64-pc-windows-msvc (default)

active toolchain
----------------

stable-x86_64-pc-windows-msvc (default)
rustc 1.54.0 (a178d0322 2021-07-26)

My machine seems to have MSVC toolchain installed. But how do I use it to compile my project?

In the root of the project, where Cargo.toml places, run cargo build to build and cargo run to run.

Did you generate the hello.lib file when compiling this project? How is it generated? Where is the file saved?

At the bottom of that reply I gave instructions for compiling and executing the program, and also ran ls so you could see what was generated.

$ clang -c hello.c -o hello.o
$ ar rc libhello.a hello.o
$ ls
build.rs  Cargo.toml  hello.c  hello.o  libhello.a  src      <----- libhello.a
$ cargo run
   Compiling repro v0.1.0 (/tmp/repro)
    Finished dev [unoptimized + debuginfo] target(s) in 0.16s
     Running `target/debug/repro`
Hello!

Thank you very much! It's OK! :smiley:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.