Solved

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

Posted on 2014-01-08
5
578 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 32

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 30

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 32

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 30

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 30

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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
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 fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

743 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

11 Experts available now in Live!

Get 1:1 Help Now