How can I get rid of the __imp__ prefix in the linker in VC++?
The __imp__
prefix appears whenever you are linking to a DLL. It does not appear when linking to statically linked libraries. Most likely the code is generated to be linked against a DLL import lib, but you have linked it with a static lib instead.
The prefix is added when you mark the imported function with __declspec(dllimport)
- make sure your imports are not using this when not linking against a DLL.
Linking error LNK2019 in MSVC, unresolved symbols with __imp__ prefix, but should be from static lib
From what I remember of my Windows days, in MinGW-built DLLs, the __imp__
symbol prefix is used for the trampoline function that calls into the DLL proper. This symbol is then provided by a small static library with the extension .dll.a
.
When you include libssh headers, you need to set a #define
to indicate that you're expecting to link statically. If you don't, the libssh functions in the header will be declared __declspec(dllimport)
and so the __imp__
symbols will be expected at link time.
I had a look at the libssh source and found this at the top of libssh.h
:
#ifdef LIBSSH_STATIC
#define LIBSSH_API
#else
#if defined _WIN32 || defined __CYGWIN__
#ifdef LIBSSH_EXPORTS
#ifdef __GNUC__
#define LIBSSH_API __attribute__((dllexport))
#else
#define LIBSSH_API __declspec(dllexport)
#endif
#else
#ifdef __GNUC__
#define LIBSSH_API __attribute__((dllimport))
#else
#define LIBSSH_API __declspec(dllimport)
#endif
#endif
#else
#if __GNUC__ >= 4
#define LIBSSH_API __attribute__((visibility("default")))
#else
#define LIBSSH_API
#endif
#endif
#endif
You need to define LIBSSH_STATIC
, either through #define
before the #include <libssh.h>
line, or as a /D
option. Since you're using CMake, you'll probably do this through add_definitions
in CMakeLists.txt
.
What is the difference between _imp and __imp?
This is fairly straight-forward identifier decoration at work. The imp_
prefix is auto-generated by the compiler, it exports a function pointer that allows optimizing binding to DLL exports. By language rules, the imp_ is prefixed by a leading underscore, required since it lives in the global namespace and is generated by the implementation and doesn't otherwise appear in the source code. So you get _imp_
.
Next thing that happens is that the compiler decorates identifiers to allow the linker to catch declaration mis-matches. Pretty important because the compiler cannot diagnose declaration mismatches across modules and diagnosing them yourself at runtime is very painful.
First there's C++ decoration, a very involved scheme that supports function overloads. It generates pretty bizarre looking names, usually including lots of ? and @ characters with extra characters for the argument and return types so that overloads are unambiguous. Then there's decoration for C identifiers, they are based on the calling convention. A cdecl function has a single leading underscore, an stdcall function has a leading underscore and a trailing @n that permits diagnosing argument declaration mismatches before they imbalance the stack. The C decoration is absent in 64-bit code, there is (blessfully) only one calling convention.
So you got the linker error because you forgot to specify C linkage, the linker was asked to match the heavily decorated C++ name with the mildly decorated C name. You then fixed it with extern "C"
, now you got the single added underscore for cdecl, turning _imp_
into __imp_
.
Linker can not find __imp_clock and __imp_time64 when building a sample of GTSAM
__imp_
prefix in unresolved external runtime library symbol from the linked library means the library was built with DLL runtime (/MD
in C++ -> Code Generation -> Runtime Library
).
If you build the application with static runtime (/MT
) the symbols from the DLL runtime will be unresolved. Runtime settings should be the same for all compilation units.
Semantics of __imp_ symbols
Members of kernel32.lib
are not normal object files but special placeholders. From the PE/COFF spec:
Traditional import libraries, that is, libraries that describe the
exports from one image for use by another, typically follow the layout
described in section 7, “Archive (Library) File Format.” The primary
difference is that import library members contain pseudo-object files
instead of real ones, in which each member includes the section
contributions that are required to build the import tables that are
described in section 6.4, “The .idata Section.” The linker generates
this archive while building the exporting application.The section contributions for an import can be inferred from a small set of information. The linker can either generate the complete,
verbose information into the import library for each member at the
time of the library’s creation or write only the canonical information
to the library and let the application that later uses it generate the
necessary data on the fly.[...] a short import library is written as follows:
Archive member header
Import header
Null-terminated import name string
Null-terminated DLL name string
This is sufficient information to accurately reconstruct the entire contents of the member at the time of its use.
In kernel32.lib
on my machine, __imp_ExitProcess
is mentioned in the first and second linker members (symbol list) and point to the specific pseudo-object describing the import:
Archive member name at 8: /
50107C36 time/date Thu Jul 26 01:07:34 2012
uid
gid
0 mode
106CA size
correct header end
2515 public symbols
[...]
3C874 ExitProcess
3C874 __imp_ExitProcess
[...]
Archive member name at 3C874: KERNEL32.dll/
50107639 time/date Thu Jul 26 00:42:01 2012
uid
gid
0 mode
2D size
correct header end
Version : 0
Machine : 8664 (x64)
TimeDateStamp: 50107639 Thu Jul 26 00:42:01 2012
SizeOfData : 00000019
DLL name : KERNEL32.dll
Symbol name : ExitProcess
Type : code
Name type : name
Hint : 371
Name : ExitProcess
So, as you can see, the data in .lib explicitly says that it refers to an import name ExitProcess
from the DLL KERNEL32.dll
. The linker can use this to build necessary metadata in the import section.
Now, the above only discussed how the __imp_ExitProcess
symbol is resolved. I'm not 100% sure but I think if a symbol (e.g. ExitProcess
) has been resolved to such an import stub, and it does not start with __imp_
, then the linker has to generate a jump stub (for code symbols), or an indirect access (for data accesses) to the IAT slot.
Related Topics
Istream Behavior Change in C++ Upon Failure
How to Write to a Memory Buffer With a File*
Reading a Line from Ifstream into a String Variable
Stl Remove Doesn't Work as Expected
Is Std::Pair<Int, Std::String> Ordering Well-Defined
Workaround for Template Argument Deduction in Non-Deduced Context
How Non-Member Functions Improve Encapsulation
Finding Smallest Value in an Array Most Efficiently
How to Get a Copy of the File Libstdc++.So.6.0.15
Where Are Temporary Object Stored
C++: Converting Hexadecimal to Decimal
Does a Declaration Using "Auto" Match an Extern Declaration That Uses a Concrete Type Specifier
Why Does -Int_Min = Int_Min in a Signed, Two's Complement Representation
Const Correctness for Value Parameters
In Either C or C++, Should I Check Pointer Parameters Against Null/Nullptr
How to Guarantee Order of Argument Evaluation When Calling a Function Object
Does Boost Have a Datatype for Set Operations That Is Simpler Than the Stl