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.

2 Likes

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.

Chrefr,
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.