GCC style weak linking in Visual Studio?
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++.
Is it possible to determine (at runtime) if a function has been implemented?
On GNU gcc / Mingw32 / Cygwin you can use Weak symbol:
#include <stdio.h>
extern void __attribute__((weak)) callMeIfYouDare();
void (*callMePtr)() = &callMeIfYouDare;
int main() {
if (callMePtr) {
printf("Calling...\n");
callMePtr();
} else {
printf("callMeIfYouDare() unresolved\n");
}
}
Compile and run:
$ g++ test_undef.cpp -o test_undef.exe
$ ./test_undef.exe
callMeIfYouDare() unresolved
If you link it with library that defines callMeIfYouDare though it will call it. Note that going via the pointer is necessary in Mingw32/Cygwin at least. Placing a direct call callMeIfYouDare() will result in a truncated relocation by default which unless you want to play with linker scripts is unavoidable.
Using Visual Studio, you might be able to get __declspec(selectany) to do the same trick: GCC style weak linking in Visual Studio?
Update #1: For XCode you can use __attribute__((weak_import))
instead according to: Frameworks and Weak Linking
Update #2: For XCode based on "Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)" I managed to resolve the issue by compiling with the following command:
g++ test_undef.cpp -undefined dynamic_lookup -o test_undef
and leaving __attribute__((weak))
as it is for the other platforms.
static linking in gcc (mingw)
When the linker scans the library files, it only links the object code necessary to resolve the symbols not resolved by earlier object code or libraries. Unreferenced object code from archives will not be linked.
Specifying redundant libraries may extend the build time. You can help that by specifying the most used libraries first, but in all but the largest projects that is unlikely to be significant.
template specialization, different behavior on windows vs gcc?
The first thing is that your code is in violation of the ODR rule if any translation unit includes the header and causes the definition of the specialization without the compiler seeing a declaration. Since that is undefined behavior the fact that one compiler accepts it and the other rejects it is well within reason.
The correct code, as you already figured out is to provide the declaration of the specialization, and that will work in any compiler.
As of why it seems to work or even why does it actually work in gcc, this is most probably a matter of how the code is generated and the linker processes the object files. In particular in gcc the compiler will generate the specialization in the translation unit that needs it (and does not see your own specialization), but it will be marked as a weak symbol. The gcc linker will accept a symbol being multiply defined if all but [at most] one definitions are weak, leaving the strong symbol in the final executable.
Working code tested on Linux throws 'error C3646' on win 7, Visual Studio 12
__attribute__
Is GCC specific. It's a non standard extension.
That's why MSVC is complaining.
Here is a good answer on how to find a workaround to have the equivalent working on Visual Studio for.
In fact, it depends of your usage of the __attribute__
extension. But it is difficult to find an equivalent in MSVC.
Related Topics
How to Switch Between Blas Libraries Without Recompiling Program
External Library Throws Undefined Reference Errors in Qt Creator
Returning Temporary Object and Binding to Const Reference
Inspecting Standard Container (Std::Map) Contents with Gdb
Force Gcc to Notify About Undefined References in Shared Libraries
Is Auto as a Parameter in a Regular Function a Gcc 4.9 Extension
Getting Libcurl to Work with Visual Studio 2013
Using Qsocketnotifier to Select on a Char Device
How to Compile Curlpp on Ubuntu
Using a Stl Map of Function Pointers
How to Access the Underlying Container of Stl Container Adaptors
What Default Promotions of Types Are There in the Variadic Arguments List
Singleton Instance Declared as Static Variable of Getinstance Method, Is It Thread-Safe
Convert Float to String with Precision & Number of Decimal Digits Specified