Solved

Problem linking a LIB, a DLL and a EXE together in VisualStudio 2010

Posted on 2014-01-08
5
585 Views
Last Modified: 2014-01-13
Hi everybody,

I encountered a problem with a project which contains one LIB, one DLL and one EXE in a way the DLL uses functions from the LIB, the EXE uses function from the LIB and the DLL.

In this case it seems all symbols exported by the LIB are linked twice, once into the DLL, once into the EXE. This at least blows up the resulting binaries. Further this causes i.e. global variables from the LIB aren't really global, there's one instance in the DLL and another one in the EXE, so the use of global variables from the LIB doesn't work as expected.

Does anyone know if there's a way to workaround this? Since for the DLL a LIB is built too maybe it's possible to link the other LIB into it - any ideas?

You can follow these steps if you want to reproduce the problem:

- Create a solution with a console application (below called LibTest), a LIB (BaseLib) and a DLL (ExtLib)
- In 'Common Properties->Framework and References' add the LIB as reference in the DLL and add both the LIB and the DLL as reference in the EXE.
- Implement the following functions in the appropriate files:
// BASE.H
#include <ostream>

extern int baseval;
extern void foo( std::ostream& os );

// BASE.CPP
#include "Base.h"

int baseval = 42;

void foo( std::ostream& os )
{
	os << "foo() called, &foo = 0x" << std::hex << &foo << ", &baseval = 0x" << &baseval << std::endl;
}

Open in new window

// EXTLIB.H
#include <iostream>

#ifdef EXTLIB_EXPORTS
#define EXTLIB_API __declspec(dllexport)
#else
#define EXTLIB_API __declspec(dllimport)
#endif

EXTLIB_API void bar( std::ostream& os );

// EXTLIB.CPP
#include "ExtLib.h"
#include "../BaseLib/Base.h"

EXTLIB_API void bar( std::ostream& os )
{
	foo( os );
}

Open in new window

// LIBTEST.CPP
#include <iostream>
#include <tchar.h>

#include "../BaseLib/Base.h"
#include "../ExtLib/ExtLib.h"

int _tmain(int argc, _TCHAR* argv[])
{
	foo( std::cout );
	bar( std::cout );
	return 0;
}

Open in new window

(I unset the 'Use precompiled header' setting, you can do so too or add #include "stdafx.h" to every CPP file).

When I run this program the output is like
foo() called, &foo = 0x00C910A0, &baseval = 0x00C93018
foo() called, &foo = 0x5AD21080, &baseval = 0x5AD23010

Open in new window

When I change the DLL to build to a LIB instead the same doesn't happen, there the output looks like
foo() called, &foo = 0x00AE10E0, &baseval = 0x00AE3018
foo() called, &foo = 0x00AE10E0, &baseval = 0x00AE3018

Open in new window

Thanks in advance,

best regards,

ZOPPO
0
Comment
Question by:Zoppo
  • 3
  • 2
5 Comments
 
LVL 33

Assisted Solution

by:sarabande
sarabande earned 500 total points
ID: 39767911
a lib is technically only a collection of object files. because of that if you use the lib in two executables, you would necessarily have the symbols twice and any static or global symbol has an instance in the exe or dll. that is same as you would add the same source file to two projects where you also get all symbols twice.

if you want to change that you have to turn the lib into a dll or you write wrappers in the dll for all functions of the lib and export them.

i am currently working on a project with about 50 dll's and no lib. we have both methods that either a bundle of functions has moved to a new dll, or that a function needed in a second dll was exported from a dll.

the visual studio references would add nothing to that, as far as i know. they are for "intellisense" purposes only.

Sara
0
 
LVL 31

Author Comment

by:Zoppo
ID: 39775898
Hi Sara,

thanks for the comment. And yes, that's even what I thought.

Unfortunateley we exactly want to avoid the need to create a DLL for each library.

I thought there maybe could be a possibility to link the LIB into the "Import Library" LIB file which is created with the DLL for implicit linking. Thus I think it would be possible to avoid those duplicate symbols.

Do you think this is possible?

Best regards,

ZOPPO
0
 
LVL 33

Accepted Solution

by:
sarabande earned 500 total points
ID: 39776217
the 'import library' added to a dll actually is wrapper code, a bundle of functions which have the same interface as the original dll functions, but have no code beside of calling into the original dll function.

for a function in a static lib that should be shared, you would need to write the wrapper code yourself. you would need a dll which is 'host' of the static library and the dll would link against it. you would need code for the wrappers and a second library (project) that contains the wrappers. so actually you do the same as you would get automatically when turning the lib to a dll. the only advantage i see is that you could have one dll for multiple small(er) libraries and therefore less issues if the functions were mutually dependent on each other.

i worked with static libraries in the past but found them inconvenient when the project grows. in current projects i add functions to dlls and export them. or if i have a bundle of functions, i put them into a class and export the class. the important question then is which dll is suitable to take the function/class. for example if i have a function in dll1 that i need in dll2, i firstly check whether dll2 was built prior to dll1 in the build order. if that isn't the case i have to move the function (or class) to dll3 where both dll1 and dll2 can be dependent on. after that the function was exported and can used both by dll1 and dll2.

Sara
0
 
LVL 31

Author Comment

by:Zoppo
ID: 39778489
Thanks again. And yes, you're right, I managed to link the LIB into the DLL's Import Library so the EXE doesn't need to link the LIB itself, but there still are two copies of the symbols, one within the DLL and one with its Import Library. So it seem's there's no way to use a static LIB the way I like :o(

Best regards,

ZOPPO
0
 
LVL 31

Author Closing Comment

by:Zoppo
ID: 39778491
No solution possible. I want to assign the points to Sara anyway for the good explanation ...
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Does the idea of dealing with bits scare or confuse you? Does it seem like a waste of time in an age where we all have terabytes of storage? If so, you're missing out on one of the core tools in every professional programmer's toolbox. Learn how to …
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

24 Experts available now in Live!

Get 1:1 Help Now