Help debugging linker issue (Microsoft Toolchain verbosity)

I have a native module built with the Visual Studio 2019 toolchain in C and I'm trying to link and import it in Rust. I am having a linker error.

Is there a way to turn up the verbosity on the linker toolchain so it works like the MS linker? In Visual Studio I can have the linker print the symbol with munging/decorations that it's trying to match. I think Rust in Windows is using the Microsoft linker so I should be able to force it to tell me what modules it "sees" in the DLL I have given it, and what module it is "failing to match".

second_rust_lib_v0.second_rust_lib_v0.ay01u8ua-cgu.6.rcgu.o : error LNK2019: 
unresolved external symbol output referenced in function print_something

The module I'm trying to link is called output and I'm calling it from function print_something. The compile phase seems fine, but I can't get cargo to link to this module.

If I select dynamic library (this is a dynamic lib), Rust wants to link with _imp_output, so I set it to static, and Rust links with output. I know it is finding the .lib/.dll module I want to load because if I change the name in the source, the linker complains "can't open" mylib.dll.

This is the function export information from dumpbin.exe /exports on the *.lib file:

 31    ?output@@YAXPEBDZZ (void __cdecl output(char const *,...))

Do you declare the function in C with extern "C"? Because it seems that VC++ mangles the name.

I don't have control over how the external library is defined. All I have is it's *.h header declaration and access to the DLL package at link time.
I suppose I could force mangle the name using the dumpbin.exe output... I'll try that it might work.

By that, I can declare the external name of the function to Rust to be that of the mangled name I see from dumpbin.exe and see if that flies. Thanks!

You can do that, just note that the mangling schema is unspecified in C++, and can change between compilers or even versions of the same compiler.

1 Like

Yes, understood.
I would have to manage this via a build script somehow eventually. Perhaps I can create a migration crate that will manage this long term. For now I just want to access 1 function and see if I can get a proof of concept task integrated into our custom environment.

Bindgen can parse C++ headers and generate corresponding Rust function and type declarations, including name mangling. It's designed to be used in build scripts so the generated bindings match the target platform.


Thanks, I'm aware of bindgen, and understand it can be used both to bind native C to Rust and also Rust to C.

I'm at the moment just wanting to link one API call from a native C library to Rust, and link one Rust call to my C environment. Essentially a "hello world" which the user calls a Rust function from C, and inside the Rust function it calls our native "output" function. This is the first step in proving to myself that I can be productive in Rust.

I have to be able to make calls into a Rust DLL from C, and that Rust DLL must be able to make calls into our proprietary C/C++ API library. If all that works, I can then consider which tasks I could consider that are appropriate for Rust migration. The overhead to dig into and port our entire API into a series of Rust crates is more than I want to tackle just to do the proof of concept.

It's clear to me how bindgen can generate C headers from Rust code, it's not yet clear to me how the process of using bindgen to map native C into Rust works. I'm brute forcing that at the moment.

I found a tutorial on using bindgen to build C->Rust wrapper crates, but decided that was more work than I needed for just doing 1 API function at this point.

Want to thank you for the "mangling schema is unspecified in C++" again. That really jogged my brain. I have my C native code calling a Rust DLL, which in turn is dependent on the native DLL function "output" now. It's all pretty impressive that I could do this in a little over a day from "hello world".

I now have a baseline framework with which to consider doing other tasks in Rust instead of C.

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.