I know how to link against libraries in Unix-ish contexts: If I'm working with .a
or .so
files, I specify the root search directory with -L/my/path/to/lib/
and for libMylib I add -lMyLib
.
But what if I have
.dll
(e.g. in the Windows\System32
directory)?.dll
(in Windows\System32
) and a .lib
(someplace else)?These DLLs are by some other party; I don't have access to their sources - but do have access to the corresponding include files, against which I manage to compile.
@einpoklum Converting my comment to an answer: @n.18e9 is correct in that you must use the full path name for the lib file without any -L or -l options.
g++ -o foo.exe foo.o c:\something\somethingelse\some.lib
. You can also link directly to the Windows DLL file g++ -o foo.exe foo.o c:\something\somethingelse\some.dll
.
Important - make sure you are linking to a lib file (and associated dll) generated for a 64-bit platform (on MSVC target X64, not Win32).
OK you wanted an example, well let's go.
Here are two examples using gcc/g++ to link to a Windows native DLL which exports plain C functions (using here x86_64-w64-mingw32/8.3.0 on Windows 10).
I'm using my own free xmlsq library as an example https://www.cryptosys.net/xmlsq. You can download the core native DLL and all the source code quoted below. Make sure you use the 64-bit DLL.
The native Windows DLL diXmlsq.dll
is written entirely in plain C code and exports simple C functions (extern "C").
In particular, for this example, it exports a XMLSQ_Gen_Version
function that returns an integer value.
The DLL was compiled using MSVC 12.0 targetting the X64 platform. The associated library file generated by MSVC is diXmlsq.lib
.
I should add that this DLL works exactly the same as a Windows "Win32 API" DLL, so the instructions here should work for the standard Windows libraries in Windows\System32
(again make sure you link against the 64-bit version).
Example 1. A plain C interface.
Both these commands compile without warning on my system:
> gcc -o test-ver test-ver.c "C:\fullpath\to\x64\diXmlsq.lib"
> gcc -o test-ver test-ver.c "C:\fullpath\to\x64\diXmlsq.dll"
diXmlsq.dll
is compiled using the following definition file.
(You could alternatively use __declspec(dllexport)
)
Ref: https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll?view=msvc-160
diXmlsq.def
LIBRARY "diXmlsq"
EXPORTS
XMLSQ_Gen_Version
diXmlsq.h
- the C interface to diXmlsq.dll
#ifdef __cplusplus
extern "C" {
#endif
long __stdcall XMLSQ_Gen_Version(void);
#ifdef __cplusplus
}
#endif
To call the core function in a plain C program:
test-ver.c
#include <stdio.h>
#include "diXmlsq.h"
int main(void)
{
long n;
n = XMLSQ_Gen_Version();
printf("Version = %ld\n", n);
return 0;
}
Example 2. A C++ interface.
Both these commands compile without warning using g++ .
> g++ -o test-simple test-simple.cpp xmlsq.cpp "C:\fullpath\to\x64\diXmlsq.lib"
> g++ -o test-simple test-simple.cpp xmlsq.cpp "C:\fullpath\to\x64\diXmlsq.dll"
The idea of the C++ interface is to be an interface to the plain C library using the more convenient STL types like std::string
and std::vector
.
To keep things simple we'll just demonstrate the Gen::Version
method.
Extracts of the C++ code follow:
test-simple.cpp
- a test C++ program.
#include <iostream>
#include "xmlsq.hpp"
int main()
{
std::cout << "xmlsq::Gen::Version=" << xmlsq::Gen::Version() << std::endl;
}
xmlsq.hpp
- the C++ interface
namespace xmlsq
{
class Gen {
private:
Gen() {} // Static methods only, so hide constructor.
public:
/** Get version number of core diXmlsq DLL. */
static int Version();
};
}
xmlsq.cpp
- the C++ implementation.
#include "diXmlsq.h"
#include "xmlsq.hpp"
namespace xmlsq
{
int Gen::Version() {
int n = XMLSQ_Gen_Version();
return n;
}
}
Example 3. Attempting to link to the 32-bit library by mistake.
> gcc -o test-ver test-ver.c "C:\fullpath\to\Win32\diXmlsq.lib"
C:/Strawberry/c/bin/../lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
C:\Users\user\AppData\Local\Temp\cce27Dhl.o:test-ver.c:(.text+0xe):
undefined reference to `XMLSQ_Gen_Version'
collect2.exe: error: ld returned 1 exit status
If you can link against a .lib
in Cygwin or MinGW, then you can (indirectly) link against a DLL.
In the MSVC world, it is not unusual to create an import library along with a DLL. It is a static library (.lib
) that loads the DLL and wraps the interface of the DLL. You just call the wrapper functions in the (static) import library and let the import library do all the DLL-related things.
Linking against the .lib
file in Cygwin or MinGW is possible. Example:
g++ -o myprg myprg.o -lShlwapi
This links against Shlwapi.lib. (The library must be in the local directory or in the library path of the linker.)
Linking against import libraries of DLLs works the same way.
Note 1: Keep in mind the different ABIs and name mangeling. However, calling plain C functions in DLL or LIB files will work in most cases.
Note 2: Keep in mind that g++ requires the libraries to be specified in the correct order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With