GCC style weak linking in Visual Studio?
Asked Answered
B

6

57

GCC has the ability to make a symbol link weakly via __attribute__((weak)). I want to use the a weak symbol in a static library that users can override in their application. A GCC style weak symbol would let me do that, but I don't know if it can be done with visual studio.

Does Visual Studio offer a similar feature?

Broeker answered 18/2, 2010 at 17:9 Comment(3)
See Windows Static Library with Default Functions. Is this what you're trying to achieve?Trieste
See the answer by Michael Burr -- MSVC actually defaults to this behaviour. If you override a symbol that is already defined in a dependency lib, the symbol in the .lib will be silently ignored.Subinfeudate
VC++ does not expose an explicit way of declaring symbols as weak – but there are two alternatives that come close. Check: ofekshilon.com/2014/02/10/linker-weak-symbolsHydromechanics
L
19

MSVC++ has __declspec(selectany) which covers part of the functionality of weak symbols: it allows you to define multiple identical symbols with external linkage, directing the compiler to choose any one of several available. However, I don't think MSVC++ has anything that would cover the other part of weak symbol functionality: the possibility to provide "replaceable" definitions in a library.

This, BTW, makes one wonder how the support for standard replaceable ::operator new and ::operator delete functions works in MSVC++.

Literator answered 18/2, 2010 at 17:46 Comment(3)
Does MSVC++ have something like this macro that works with main(), in order to let any code including this file override main()?Bryanbryana
::operator new ships as object code inside nothrownew.obj. I assume the CRT uses a similar concept to the __fltused-trick to have the object code pulled into the module unless it has been defined elsewhere. The classical linker rules for OBJs and LIBs are described at The Old New Thing.Koala
@Koala Fixed link: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can’t override an OBJ.Worley
W
99

You can do it, here is an example in C:

/*
 * pWeakValue MUST be an extern const variable, which will be aliased to
 * pDefaultWeakValue if no real user definition is present, thanks to the
 * alternatename directive.
 */

extern const char * pWeakValue;
extern const char * pDefaultWeakValue = NULL;

#pragma comment(linker, "/alternatename:_pWeakValue=_pDefaultWeakValue")
Waxbill answered 17/7, 2012 at 19:14 Comment(10)
This is a correct answer. Can you find some documentation to back it up?Broeker
It is an undocumented feature. I've stumbled upon it accidentally while browsing msvcrt source code.Waxbill
@Ringo If the pWeakValue is defined already, can it still be replaced by the alternatename option.Hydromechanics
At least with VS2019, this also works for functions, provided they are declared extern "C" in C++ code. At least I couldn't get it to work with mangled C++ function names, but it did work with extern "C" functions.Palaeo
Raymond Chen wrote a blog post about /ALTERNATENAME linker switch devblogs.microsoft.com/oldnewthing/20200731-00/?p=104024Waxbill
The problem is, pDefaultWeakValue and pWeakValue are 2 different symbols. So this approach only allows you to define a customized version of pWeakValue and fall back to pDefaultWeakValue if not. If there's one function pWeakValue() that is defined and used, you cannot replace it without changing the implementation name to pDefaultWeakValue() and provide your own implementation of pWeakValue() because there's only 1 symbol name.Hydromechanics
@Palaeo Re: "with VS2019, this also works for functions": can you provide a demo? In C I cannot make it work: godbolt.org/z/xqzdM51dc. Any ideas?Bludge
@Palaeo As I understand, in contrast with GCC's __attribute__((weak)), MSVC's /alternatename does not have an effect on compiler. If f is a weak attributed function, then GCC does not optimize if (f) to if (1). If f is a function with /alternatename, then MSVC optimizes if (f) to if (1).Bludge
@Bludge As Michael Burr points out in his answer, no action is needed to get this behavior to work under MSVC. godbolt.org/z/zcsKMf95x I've overridden puts() there simply by defining it in the source file, and my version is used in preference to the one in the standard libraryPalaeo
I did not need to add '_' before the symbols in the linker comment.Zebu
L
19

MSVC++ has __declspec(selectany) which covers part of the functionality of weak symbols: it allows you to define multiple identical symbols with external linkage, directing the compiler to choose any one of several available. However, I don't think MSVC++ has anything that would cover the other part of weak symbol functionality: the possibility to provide "replaceable" definitions in a library.

This, BTW, makes one wonder how the support for standard replaceable ::operator new and ::operator delete functions works in MSVC++.

Literator answered 18/2, 2010 at 17:46 Comment(3)
Does MSVC++ have something like this macro that works with main(), in order to let any code including this file override main()?Bryanbryana
::operator new ships as object code inside nothrownew.obj. I assume the CRT uses a similar concept to the __fltused-trick to have the object code pulled into the module unless it has been defined elsewhere. The classical linker rules for OBJs and LIBs are described at The Old New Thing.Koala
@Koala Fixed link: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can’t override an OBJ.Worley
V
16

MSVC used to behave such that if a symbol is defined in a .obj file and a .lib it would use the one on the .obj file without warning. I recall that it would also handle the situation where the symbol is defined in multiple libs it would use the one in the library named first in the list.

I can't say I've tried this in a while, but I'd be surprised if they changed this behavior (especially that .obj defined symbols override symbols in .lib files).

Vladamir answered 18/2, 2010 at 17:46 Comment(4)
A brief test with VS 2010 RC indicates that the behavior I described is still there.Vladamir
In a way I prefer this behavior to the weak attribute. This has always been the behavior in MS compilers as far as I know (been using MS compiler since 1988 (C5.0). I was puzzled by this when I came across it in GCC a few years ago. I think it's logical to use the first occurrence of the function found when linking although care has to be taken that you are linking the function you think you are.Weatherboarding
Why can't Microsoft make this more explicit ? And I can't find any official document describing this behavior. I am wondering if this is by design or by accident...Hydromechanics
@MichaelBurr Twelve years later, the current MSVC compiler is still working this way: godbolt.org/z/4x9Pz8bvbPalaeo
D
5

The only way i know. Place each symbol in a separate library. User objects with overrides also must be combined to library. Then link all together to an application. User library must be specified as input file, your lib's must be transfered to linker using /DEFAULTLIB: option.

Dietetics answered 17/10, 2012 at 15:22 Comment(0)
H
4

From here:

... if a needed symbol can be satisfied without consulting a library, then the OBJ in the library will not be used. This lets you override a symbol in a library by explicitly placing it an OBJ. You can also override a symbol in a library to putting it in another library that gets searched ahead of the one you want to override. But you can’t override a symbol in an explicit OBJ, because those are part of the initial conditions.

This behavior results from the algorithm adopted by the linker.

So for short, to override a function,

  • With GCC, you must use the __attribute__((weak)). You cannot rely on the input order of object files into the linker to decide which function implementation is used.

  • With VS toolchain, you can rely on the order of the object/lib files and you must place your implementation of the function before the LIB that implements the original function. And you can put your implementation as an OBJ or LIB.

Hydromechanics answered 2/8, 2021 at 8:55 Comment(0)
M
2

There isn't an MS-VC equivalent to this attribute. See http://connect.microsoft.com/VisualStudio/feedback/details/505028/add-weak-function-references-for-visual-c-c. I'm going to suggest something horrible: reading the purpose of it here: http://www.kolpackov.net/pipermail/notes/2004-March/000006.html it is essentially to define functions that, if their symbols exist, are used, otherwise, are not, so...

Why not use pre-processor for this purpose, with the huge caveat of "if you need to do this at all"? (I'm not a fan of recommending pre-processor).

Example:

#ifdef USE_MY_FUNCTION
     extern void function();
#endif

then call appropriately in the application logic, surrounded by #ifdef statements. If your static library is linked in, as part of the linking in process, tweak the defines to define USE_MY_FUNCTION.

Not quite a direct equivalent and very ugly but it's the best I can think of.

Maltose answered 18/2, 2010 at 17:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.