4

I come from a Delphi world where importing a DLL function statically is pretty easy. All you need to do is specify the function name and the module like this:

function GetTickCount : DWORD; stdcall; external 'Kernel32.dll';

Why in C++ must I use kernel32.lib in order to import the function? Why can't I simply tell the linker to import that function just like in Delphi?

I know it may sound noobish for manny of you, but coming in the C++ world from Delphi can really get confusing.

NGLN
  • 43,011
  • 8
  • 105
  • 200
opc0de
  • 11,557
  • 14
  • 94
  • 187
  • 1
    That's really down to history. It's just always been done that way in the C and C++ world. The .lib files used for importing functions from DLLs contain import stubs. The Delphi approach has the compiler generating those stubs. In fact it is absolutely unrelated to ordinal vs named import as per the answer that you accepted. Some simple experimentation can confirm that. – David Heffernan Oct 12 '12 at 08:24
  • There's a similar question here: http://stackoverflow.com/questions/6957061/why-do-i-need-to-link-a-lib-file-to-my-project In fact it's pretty much a duplicate of this one – David Heffernan Oct 12 '12 at 08:32
  • Welcome to the C world where everything is more complicated than needs to be – Gabriel Aug 10 '19 at 11:45

3 Answers3

8

The C++ toolchain takes a couple of steps to do what Delphi can do in one step. When declaring an external DLL function in C++, there is no (standard) way to indicate which named DLL the function can actually be found in. As far as the compiler is concerned, the declared function is simply extern and there must be a definition that can be found somewhere by the linker.

To connect the named function to the DLL in which it can be found, the C++ toolchain requires an "import library" that contains import stubs that the linker knows what to do with. When finding a function defined by an import stub, the linker creates a DLL function reference for the specific function name in the corresponding DLL (as indicated by the import stub).

In Delphi, the language designers allowed the programmer to specify the associated DLL directly in the source code. The Delphi compiler can then directly generate the reference to the external DLL without the use of the import stub step.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 1
    I guess C++ really needs an update on this :). Thanks for enlightening me. – opc0de Oct 12 '12 at 06:46
  • @opc0de: As a platform independent language standard, C++ itself can't do much. Delphi was always platform specific (afair Linux and Windows). – Sebastian Mach Oct 12 '12 at 08:08
  • @phresnel take a look at free pascal it's cross platform – opc0de Oct 12 '12 at 08:20
  • @opc0de: Though one would have to add "Windows" and "Unix" and other operating systems into the C++ ISO standard. Free Pascal on a GameBoy won't have DLL-files, I guess. The one to blame is more the compiler vendor, who has to use `#pragma` and the likes for platform specifics, but not C++ itself :) – Sebastian Mach Oct 12 '12 at 08:31
  • @DavidHeffernan: Thanks for the reminder, I've had a go at reworking my answer. – Greg Hewgill Oct 15 '12 at 07:46
  • @GregHewgill Thanks a lot. I appreciate your edit. Coincidentally, the issue of ordinal imports in Delphi came up in a question yesterday: http://stackoverflow.com/questions/12886675/the-procedure-entry-point-function-could-not-be-located-in-the-dynamic-link-li – David Heffernan Oct 15 '12 at 07:59
  • "Delphi was always platform specific" - hm.... not really. especially not these days... I think the C++ unit layout (.Cpp + .H file) was simply a very bad idea. Too late to fix it now! – Gabriel May 08 '19 at 13:39
4

Your question is really only an issue with the Microsoft C++ compiler (MSVC) which requires the use of an "import library" as an intermediate step to bind the symbols (i.e., function names) to the ordinals of the functions in the DLL. It is not a C++ issue per se. This is arguably just one more annoying quirk of the MSVC compiler, but I don't know enough about the motivation for such a scheme to comment on whether it should or could be changed or not. If I remember correctly, the C++Builder compiler also works with this mechanism, imitating MSVC.

Most other compilers align themselves to the way GCC works (GNU Compiler Collection) in terms of linking and binary interfaces. And those do not require this additional "import library", you simply specify the DLL in question as part of the libraries to link with your executable.

Btw, when it comes to differences between the C++ linkers and the Delphi linker, this issue you pointed out is only the tip of the iceberg. They are very different in much deeper ways. The C++ standard pretty much requires the linker to be fairly simple (due to the "separate compilation model"), just connecting dots, so to speak, while in Delphi linker is much more intimately linked with the compiler, and is generally smarter (and faster).

Mikael Persson
  • 18,174
  • 6
  • 36
  • 52
  • I am using Qt with MinGW and I still need to link that way.Maybe there is a way and I don't know it. I will make some research. Thanks – opc0de Oct 12 '12 at 07:08
  • 1
    @Mikael Do you have any documentation to back this up? My experience with Windows ports of gcc/g++ are that you still need to use MS format .lib import libraries. – David Heffernan Oct 12 '12 at 08:26
  • 2
    @DavidHeffernan In MinGW, you only need the MS style mechanism when dealing with MS-produced DLLs, or vice versa (producing an MSVC-friendly library for a MinGW DLL). There are tools like `dlltool` and `reimp` that do the conversion / creation of import libraries. In any case, linking a DLL and EXE that don't use the same C++ ABI is a *very bad idea*. With a C-compatible DLL, or a C++ DLL from GCC / ICC / Clang, the linker can deal with them without an import library (see http://www.mingw.org/wiki/CreateImportLibraries). GCC handles DLLs like shared-objects in Unix-like OSes. – Mikael Persson Oct 12 '12 at 18:25
1

I just submitted the following feature request to QC:

QC #109493: Add a compiler extension to import DLL functions without needing an import .lib file

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770