Proper way to link static libraries with dll

triclosan picture triclosan · Jul 16, 2015 · Viewed 32.7k times · Source

My project builds through few static libraries which should linked to main dll library gain one single dll as a result.

Using __declspec(dllexport) attribute does not lead to appearance of specified functions of static libraries to dll, libraries not linked with dll at all.

Then I tried to build each library as shared for getting proper names of exported functions and created .def file based on them. Using .def file leaded to result.

  1. Should __declspec(dllexport) and .def-file act equally in my case?

  2. Is it possible to generate a .def file from sources? Since I have C++ code I'm not able to write .def file by myself because of mangling and presence classes in API, the approach described above with temporary generated dlls is inconsistent for production.

Update

I'd like to explain in detail about the structure of my project. The solution consists of a few projects (modules).

+ 
|    
+-+ static_lib1                                          
|       +                                                
|       +--+ src                                         
|                                                        
+-+ static_lib2                                          
|       +                                                
|       +--+ src                                         
|                                                        
+-+ dynamic_lib (linked with static_lib1 and static_lib2)
        +                                                
        +--+ src

Each sub-project weakly depends on others, let's assume they are not connected for clearness. Each module has own public interface. I want to have all modules as single dynamic library so my artifact is dynamic_lib.dll, but in fact static libraries are not linked with it.

Answer

Mateusz Grzejek picture Mateusz Grzejek · Jul 16, 2015

Static libraries should not contain any __declspec or __attribute((dll...)) things. They are nothing more than multiple object files (usually *.obj or *.o), composed into one, single file.

All you need to do in order to use such library (either in .exe or .dll) is to include proper headers and link them - with Visual Studio it's pretty easy.

First of all, you need to know 1) where your static libraries are placed and 2) their exact names. Go to project properties and then General. Target name contains name for the output file, while Output directory indicates in which folder your .lib will be placed.

Note: This path may be different for every project! For multi-project solution, I always set this to a common path to avoid configuration problems.

Now, go to properties of project, that will consume this library (link with it). Go to Linker -> Input and then add name of your .lib to Additional dependencies (entries are separated with semicolon):

Linker input

You need to add all libraries you want have linked in. Also, folder, in which these libraries are placed, must added to Linker -> General -> Additional library directories. If all .libs are placed in the same place - good, otherwise copy them into shared location or add multiple entries to Additional library directories list.

And the last thing - remember, that you also need to include headers with declarations of functions and objects, that you want to use. Basic thing, I know, but has to be mentioned.


UPDATE

unresolved external when trying to use dll library in an external prodjects

Your problem is not related to linking at all. The thing is, that you misunderstood what, linking a static library exactly does.

I am guessing, that functions reported as unresolved are not used by your DLL, right? But you expect them to be inside it, right?

When your DLL refers to an external content (like function or variable), it is resolved at linking time - together with all dependencies. But that's all. If your static library has a function named print_sample_string(), but your DLL does not use it, it won't be attached to DLL image. Think about this carefully - why should it be?

Even more - functions, that are not dllexported explicitly won't be visible anyway. Functions have by default external storage - so basically, they are private DLL's content.

So to answer your question directly - if you need to use functions/variables from static_lib1.lib, attach it to client application - just like you are attaching it now to dynamic_lib. There is no other way. (*)


(*) Truly speaking - there is. You can create intermediate function in DLL, that is exported and call desired function inside:

Somewhere in dynamic_lib:

DLL_EXP_IMP long CallFunctionFromA_Lib()
{
     return some_function(); //this function is from static_lib1.lib
}

Somewhere in .exe:

long result = CallFunctionFromA_Lib(); //internally this will call function from static_lib1.lib

I can't imagine, however, why would you want to do this and not simply link A.lib and use it directly.