How do I statically link a library into a DLL? - c++

I'm in DLL hell. I have 2 DLLs let's say A.dll and B.dll which have a name collision - the same C++ class name is used in each, etc. Both DLLs are available as static libs.
Can I create a 'wrappe' DLL, say Aprime.dll which exports a similar class, methods, etc. as in A.dll, and delegates the functionality to the class in A.lib, but statically linked into the Aprime.dll? Wouldn't that avoid the name collision?
I've been trying this, but not sure I have the MSVS project set up correctly. Aprime.dll is being produced, but according to Dependency Walker Aprime.dll is still loading A.dll.
I've been searching, but most stuff I find applies only to statically linking in the CRT or MFC, which have their own switches.
I added A.lib under Linker -> Input -> Additional Dependencies.
Am I missing some magic linker command line switch or something?

Yes that method should work. The key though is to ensure that you do not include any of the original A.dll header files in the Aprime.dll header file. Otherwise if someone includes Aprime.h/pp then it will include A.h/pp and you will then have a clash again.
So you want something like:
A.h
// Library A includes
class test
{
};
B.h
// Library B includes
class test
{
}
Aprime.h
// Proxy class
class myTest
{
}
Aprime.cpp
#include "A.h"
#include "Aprime.h"
...
main.cpp
#include "Aprime.h"
#include "B.h"
...
Note that main never includes both A and B. In only includes Aprime and B. B is still static lib and Aprime is a DLL.

Yes, you can, and it's supported at a very low level by Windows. Aprime.DLL is effectively empty except for a bunch of references to A.DLL.

Related

Avoid LNK2005 by treating static libraries like DLLs?

Is it possible to "link" a static library, instead of just combining its .obj files into the .lib?
I have static library (A) which depends on Version 1 of static library B (B.1). I link A into my Executable. The executable itself depends on Version 2 of static library B (B.2). When the executable is created, the Linker complains about multiple defined symbols coming from B.1 (via A) and B.2. It is not desirable to solve this by setting /FORCE:MULTIPLE.
Why is it not possible in this case to basically "treat a static library like a DLL" in some sense?
If A would be a DLL, and linked into the executable by using its Import-Lib, everything would work out. In the resulting process, and after the Loader loaded DLL A into the process space, the definitions of B.1 (coming via the DLL) and B.2 (coming from the Image file of the Executable) would coexist just fine.
Why can the static library A not be "linked" so it would allow this coexistence as well? -Resolving all references and make them fixed in A. Or maybe marking everything what A imports from B.1 somehow as "private", so the Linker, which creates the Executable, treats all B.1 parts as internals of A, which he has nothing to do with? Hench, "embedding" A (compiled as a DLL) into the Executable?
Why can the static library A not be "linked" ... ?
because libraries are not executables (a DLL is).
So generally you cannot combine two versions of a library into one executable when there are conflicting names in both of them.
To circumvent this you could use namespaces with optionally an inline namespace for the prefered version (which can be controlled by conditional compilation ,one condition for the executable and one for the depending library). But be carefull with such strategy !
namespace libB
{
// "forward" declare namespaces
#ifdef LIB_A
inline namespace v1 {}
namespace v2 {} // not really necessary here
#else
namespace v1 {} // not really necessary here
inline namespace v2 {}
#endif
namespace v1
{ // implementation of version1
}
namespace v2
{ // implementation of version2
}
}

#pragma comment(lib) v #import?

I am still reasonably new to C++ and am trying to get my head around static libraries and DLLs. I have just inherited some code and wondered if someone could give me a clarification.
The inherited code contains two library projects, call them a and b. There is also the main project, which uses classes from both the libraries.
The bit I am confused about is this: both project a and project b, when built, output both a .dll to "..\.\Executables" and a .lib to "..\Shared\Lib". The stdafx.h of the main project includes library a with the following code:
#include ..\projectA\a_class.h
#pragma comment( lib, "..\\Shared\\Lib\\projectA.lib" )
... and it includes library b using the following code:
#import "..\..\Executables\projectB.dll"
It then utilises classes from both libraries. What is the difference between the two? Why is it that when I try and include library A using method B, it does not work (the classes are not accessible)?
Thanks in advance!
They do different things. You use #import to import a type library and to generate wrapper classes for COM objects. The fact that a type library can be a tlb or can be encapsulated in a dll (or as an ocx which is the same thing with a different name) is confusing. The only thing you missed is that #import is only ever to do with COM.
The "normal" #pragma comment(lib, "blah.lib") - which is an alternative to defining additional libs in Project Properties - is for linking to a static or dynamic library and is just used to import the functions and symbols exported by the lib itself. No wrapper classes are generated and it has nothing to do with COM.
You can read more about #import at MSDN here and more about the #pragma option at MSDN here.

Not all symbols of an DLL-exported class is exported (VS9)

I'm building a DLL from a group of static libraries and I'm having a problem where only parts of classes are exported.
What I'm doing is declaring all symbols I want to export with a preprocessor definition like:
#if defined(MYPROJ_BUILD_DLL)
//Build as a DLL
# define MY_API __declspec(dllexport)
#elif defined(MYPROJ_USE_DLL)
//Use as a DLL
# define MY_API __declspec(dllimport)
#else
//Build or use as a static lib
# define MY_API
#endif
For example:
class MY_API Foo{
...
}
I then build static library with MYPROJ_BUILD_DLL & MYPROJ_USE_DLL undefined causing a static library to be built.
In another build I create a DLL from these static libraries. So I define MYPROJ_BUILD_DLL causing all symbols I want to export to be attributed with __declspec(dllexport) (this is done by including all static library headers in the DLL-project source file).
Edit:
Note on unrefenced symbols: Linker options Keep Unreferenced Data (/OPT:NOREF) and Do Not Remove Redundant COMDATs (/OPT:NOICF) is set so that no unreferenced symbols will be removed.
Ok, so now to the problem. When I use this new DLL I get unresolved externals because not all symbols of a class is exported. For example in a class like this:
class MY_API Foo{
public:
Foo(char const* );
int bar();
private:
Foo( char const*, char const* );
};
Only Foo::Foo( char const*, char const*); and int Foo::bar(); is exported. How can that be? I can understand if the entire class was missing, due to e.g. I forgot to include the header in the DLL-build. But it's only partial missing.
Also, say if Foo::Foo( char const*) was not implemented; then the DLL build would have unresolved external errors. But the build is fine (I also double checked for declarations without implementation).
Note: The combined size of the static libraries I'm combining is in the region of 30MB, and the resulting DLL is 1.2MB.
I'm using Visual Studio 9.0 (2008) to build everything. And Depends to check for exported symbols.
Edit:
For the ones who wonder why I don't just build a DLL from each of the static libraries: I can't because they cross-reference each other (that's why I need to group them together in one a single DLL). I know, it's horrible I can't really understand the logic behind it.
Remember that when you link against a static LIB, by default the linker is only pulling in the functions, classes, and data that the client (which in this case is your DLL) actually references.
So what happens is this:
You build your static LIB, and that's fine. This LIB is 100% valid.
You now build your static DLL around the original binary LIB. It pulls in only the stuff that it actually references. It doesn't pull in the entire class definition which is what it needs to do. This DLL, though it builds, is invalid.
A client then uses the DLL, and expects to see a complete binary definition for the exported class, because that's what the client sees in the accompanying header file.
However the class has only been partially imported, and this is why you're getting those link errors.
To fix:
If you're able to, don't build your DLL off your static LIB. Build your DLL off the original source code. And build your static LIB off the original source code.
Otherwise you can possibly fiddle with linker settings but I strongly recommend option 1 above. Note that OPT:NOREF won't work here as OPT:NOREF has no effect on static LIBs.
What wont't fix it:
High-level linker tweaks like OPT:NOREF, anything involving COMDATs, etc. If you want those functions present, you have to make sure they're referenced, either by referencing them, or by telling the linker explicitly, "hey, this Symbol X is referenced".
As a side note:
Anytime I build a DLL or LIB, I build both a DLL and a LIB, using exactly the technique you're using. Having a single code base that can generate either a DLL or a LIB by toggling a setting is ideal. But building a DLL off of a (binary) static LIB when you own the source code for both... I'm having a hard time imagining when such a scenario would be necessary.
The problem is surely that you use the already-built static .lib in your DLL project. That cannot work, you have to rebuild the .lib so that the functions get the __declspec(dllexport) declarator and will be exported by the linker.
At that point, it just isn't all that useful anymore to create the DLL compatible version of the .lib in the first place. Just create two projects, one that creates the static .lib, another that creates the DLL. Technically it is possible to still use the static .lib in your DLL project but you'll have to export the functions with a .def file. That can be high maintenance if the library has a lot of exports.
This is probably years too late, but OP's complaint was that a private method (the destructor) was not exported from a dllexport'd class. Isn't that normal? No external user is allowed to call a private method.

circular dependencies between dlls with visual studio

I have a circular dependency between two functions. I would like each of these functions to reside in its own dll. Is it possible to build this with visual studio?
foo(int i)
{
if (i > 0)
bar(i -i);
}
-> should compile into foo.dll
bar(int i)
{
if (i > 0)
foo(i - i);
}
-> should compile into bar.dll
I have created two projects in visual studio, one for foo and one for bar. By playing with the 'References' and compiling a few times, I managed to get the dll's that I want. I would like to know however whether visual studio offers a way to do this in a clean way.
If foo changes, bar does not need to be recompiled, because I only depend on the signature of bar, not on the implementation of bar. If both dll's have the lib present, I can recompile new functionality into either of the two and the whole system still works.
The reason I am trying this is that I have a legacy system with circular dependencies, which is currently statically linked. We want to move towards dll's for various reasons. We don't want to wait until we clean up all the circular dependencies. I was thinking about solutions and tried out some things with gcc on linux and there it is possible to do what I suggest. So you can have two shared libraries that depend on each other and can be built independent of each other.
I know that circular dependencies are not a good thing to have, but that is not the discussion I want to have.
The reason it works on Unix-like systems is because they perform actual linking resolution at load time. A shared library does not know where its function definition will come from until it's loaded into a process. The downside of this is that you don't know either. A library can find and call functions in any other library (or even the main binary that launched the process in the first place). Also by default everything in a shared library is exported.
Windows doesn't work like that at all. Only explicitly exported things are exported, and all imports must be resolved at library link-time, by which point the identity of the DLL that will supply each imported function has been determined. This requires an import library to link against.
However, you can (with some extra work) get around this. Use LoadLibrary to open any DLL you like, and then use GetProcAddress to locate the functions you want to call. This way, there are no restrictions. But the restrictions in the normal method are there for a reason.
As you want to transition from static libraries to DLLs, it sounds like you're assuming that you should make each static library into a DLL. That's not your only option. Why not start moving code into DLLs only when you identify it as a self-contained module that fits into a layered design with no circularity? That way you can begin the process now but still attack it a piece at a time.
I deeply sympathise with your situation (as clarified by your edit), but as a firm believer in doing the correct thing, not the thing which works for now, if there's any possibility at all I think you need to refactor these projects.
Fix the problem not the symptom.
It's possible to use the LIB utility with .EXP files to "bootstrap" (build without prior .LIB files) a set of DLLs with a circular reference such as this one. See MSDN article for details.
I agree with other people above that this kind of situation should be avoided by revising the design.
This question was first in my search for 'dll cyclic dependency', and even if it is 10 years old, it is a shame that most answers points to 'refactoring' which is a very very very stupid advice for large project and was not a question anyway.
So I need to point out that cyclic dependency are not so dangerous. They are totally ok in unix/linux. They are mentioned in many msdn articles as possible situations with ways to go arround them. They happens in JAVA (compiler solving it by muilti-pass compiling). Saying that refactoring is the only way is like forbidding 'friends' in classes.
this pragraph in some begginers guide to linkers (David Drysdale) explains it well for VS-linkers.
So the trick is to use two-pass compiling: first one that will create just 'import-libs', and the second one that will generate dll's itself.
For visual studio and any graphic-ide compiling, it is probably still something strange. But if you make your own Makefiles, and have better controll of linker process and flags, than it is not so hard to do.
Using OP exampe files and mingw-gcc syntax as a concept to show (because i tested it and know for sure that it works ok on windows), one must:
- compile/link a.lib and b.lib without specifing cyclic libraries:
g++ -shared -Wl,--out-implib=a.lib -o a.dll a.obj //without specifying b.lib
g++ -shared -Wl,--out-implib=b.lib -o b.dll b.obj //without specifying a.lib
... will show 'undefined refernce errors' and fail to provide dll-s, but it will create a.lib and b.lib, which we want foor second-pass linking:
g++ -shared -Wl,--out-implib=a.lib -o a.dll a.obj b.lib
g++ -shared -Wl,--out-implib=b.lib -o b.dll b.obj a.lib
and the result is a.dll and b.dll with pretty clean method. Using Microsoft compilers should be simmilar, with their advice to switch link.exe to lib.exe (did not tested it, seems even cleaner, but probably harder to make something productive from it comparing to mingw + make tools).
How about this:
Project A
Public Class A
Implements C.IA
Public Function foo(ByVal value As C.IB) As Integer Implements C.IA.foo
Return value.bar(Me)
End Function
End Class
Project B
Public Class B
Implements C.IB
Public Function bar(ByVal value As C.IA) As Integer Implements C.IB.bar
Return value.foo(Me)
End Function
End Class
Project C
Public Interface IA
Function foo(ByVal value As IB) As Integer
End Interface
Public Interface IB
Function bar(ByVal value As IA) As Integer
End Interface
Project D
Sub Main()
Dim a As New A.A
Dim b As New B.B
a.foo(b)
End Sub
The only way you'll get around this "cleanly" (and I use the term loosely) will be to eliminate one of the static/link-time dependencies and change it to a run-time dependency.
Maybe something like this:
// foo.h
#if defined(COMPILING_BAR_DLL)
inline void foo(int x)
{
HMODULE hm = LoadLibrary(_T("foo.dll");
typedef void (*PFOO)(int);
PFOO pfoo = (PFOO)GetProcAddress(hm, "foo");
pfoo(x); // call the function!
FreeLibrary(hm);
}
#else
extern "C" {
__declspec(dllexport) void foo(int);
}
#endif
Foo.dll will export the function. Bar.dll no longer tries to import the function; instead, it resolves the function address at runtime.
Roll your own error handling and performance improvements.
As I came across this very problem recently I wanted to share a solution using CMake.
The idea is that we have two dlls a and b that have a circular dependency and one main object that calls a.dll. To make the linking work we create an additional library b_init that is compiled with the /FORCE:UNRESOLVED flag in order to allow building with incomplete symbols as it is not linking against a. Additionally, b_inits output name is b, so it will create b.lib.
In the next step we link a to the newly created b.lib. Note, the PRIVATE keyword to avoid transitive adding of b.lib to the b library below.
Here's the CMakeLists.txt:
project(circ_dll CXX)
cmake_minimum_required(VERSION 3.15)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_library(b_init SHARED b_dll.cpp)
set_target_properties(b_init PROPERTIES LINK_FLAGS "/FORCE:UNRESOLVED")
set_target_properties(b_init PROPERTIES OUTPUT_NAME "b")
add_library(a SHARED a_dll.cpp)
target_link_libraries(a PRIVATE b_init)
add_library(b SHARED b_dll.cpp)
target_link_libraries(b a)
add_executable(main main.cpp)
target_link_libraries(main a b)
It is not possible to do cleanly. Because they both depend on each other, if A changes, then B must be recompiled. Because B was recompiled, it has changed and A needs to be recompiled and so on.
That is part of the reason circular dependencies are bad and whether you want to or not, you cannot leave that out of the discussion.
Visual Studio will enforce the dependencies, generally speaking, since function addresses may change within the newly-compiled DLL. Even though the signature may be the same, the exposed address may change.
However, if you notice that Visual Studio typically manages to keep the same function addresses between builds, then you can use one of the "Project Only" build settings (ignores dependencies). If you do that and get an error about not being able to load the dependency DLL, then just rebuild both.
You need to decouple the two DLLs, placing the interfaces and implementation in two different DLLs, and then using late binding to instantiate the class.
// IFoo.cs: (build IFoo.dll)
interface IFoo {
void foo(int i);
}
public class FooFactory {
public static IFoo CreateInstance()
{
return (IFoo)Activator.CreateInstance("Foo", "foo").Unwrap();
}
}
// IBar.cs: (build IBar.dll)
interface IBar {
void bar(int i);
}
public class BarFactory {
public static IBar CreateInstance()
{
return (IBar)Activator.CreateInstance("Bar", "bar").Unwrap();
}
}
// foo.cs: (build Foo.dll, references IFoo.dll and IBar.dll)
public class Foo : IFoo {
void foo(int i) {
IBar objBar = BarFactory.CreateInstance();
if (i > 0) objBar.bar(i -i);
}
}
// bar.cs: (build Bar.dll, references IBar.dll and IFoo.dll)
public class Bar : IBar {
void bar(int i) {
IFoo objFoo = FooFactory.CreateInstance();
if (i > 0) objFoo.foo(i -i);
}
}
The "Factory" classes are technically not necessary, but it's much nicer to say:
IFoo objFoo = FooFactory.CreateInstance();
in application code than:
IFoo objFoo = (IFoo)Activator.CreateInstance("Foo", "foo").Unwrap();
because of the following reasons:
You can avoid a "cast" in application code, which is a good thing
If the DLL that hosts the class changes, you don't have to change all the clients, just the factory.
Code-completion still wroks.
Depending on your needs, you have to call culture-aware or key-signed DLLs, in which case you can add more parameters to the CreateInstance call in the factory in one place.
--
Kenneth Kasajian

Forcing symbol export with MSVC

I have a application and several plugins in DLL files. The plugins use symbols from the
application via a export library. The application links in several static libraries and this is where most of the symbols come from. This works fine as long as the application uses a symbol. If the symbol is not used there, I get linker errors when compiling the DLL.
How can I force the export of the symbols only used in the plugins?
In order to trigger the export I've tried something like this:
class MyClassExporter
{
MyClass mInstance;
public:
MyClassExporter() {}
};
static MyClassExporter TheMyClassExporter;
in one of the static libs the application is made of to force the export, which didn't work.
In response to Greg (thanks for the answer) and to clarify: The class I want to force the export for is MyClass (which has __declspec(...) defined, depending on wether I want to export or import). MyClassExport was my attempt to force the inclusion of unused (in terms of the application) symbols into the app. I want to 'touch' the symbols so that the linker recognizes them as used and includes them into the application so that it can in turn export these to my plugins. Linking the static libs into the plugins is not an option, since they contain singletons which would be duplicated (app and DLLs each have their own copy of static variables).
The /INCLUDE directive can be used to force the MSVC linker to include a symbol. Alternatively, /OPT:NOREF can be used to disable removal of unused symbols in general.
A common approach is to create a single unused function that references all objects exported for your plugins. Then you only need a single /INCLUDE directive for that function.
You probably want to look at __declspec(export/import)
#ifdef DLL_EXPORTING
#define WHDLL __declspec(dllexport)
#else
#define WHDLL __declspec(dllimport)
#endif
When linking static module into a dll it will only bring in the code that is used. I've never imported stuff from a static lib to simply re export it.
Perhaps you just need to mark it as exportable in the dll when compiling the static lib.
But that reminds me of putting std containers into exported classes and using some trickery in msvc to export the 'instance' of the specialised container. the template code is similar to your static code (in my thinking)
for instance without the template you get warnings the template code is not exported to support the class - this is MSVC specific from my understanding
template class DLL_EXPORTING std::auto_ptr<wxCursor>;
class DLL_EXPORTING imageButton : public wxWindow
{
std::auto_ptr<wxCursor> m_Cursor;
};
What I tried out to solve this was this:
build a static library with function void afunction( int ).
build a dll, linked to static lib, exporting afunction.
build an exe, using the afunction symbol.
How? Since the linker can be told to export functions using the __declspec(dllexport) directive, a dll needs no more than declare a to-be-exported symbol thusly.
The lib has a header "afunction.h" and an accompanying cpp file containing the function body:
// stat/afunction.h
namespace static_lib { void afunction(int); }
// stat/afunction.cpp
#include "afunction.h"
namespace static_lib { void afunction(int){ } }
The dll has an include file "indirect.h", containing the declaration of the function to be exported. The dll has a link-time dependency to the static lib. (Linker options: Input/Additional Dependencies: "static_library.lib")
// dll/indirect.h
namespace static_lib {
__declspec( dllexport ) void afunction(int);
}
The executable has only the indirectly included file:
#include <dll/indirect.h>
int main() { static_lib::afunction(1); }
And guess what? It compiles, links and even runs!
The "Use Library Dependency Inputs" option does the trick in VS2005!
This option can be found under Configuration Properties -> Linker -> General -> Use Library Dependency Inputs. Set to "true" to force linking in ALL symbols & code declared in every LIB specified as input to the project.
You can do the following to get the symbol to export from the DLL: define LIB_EXPORTS in the library project and nothing in either the DLL project or the DLL client project.
#ifdef LIB_EXPORTS
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endif
Turns out there is no need #include any headers from the LIB project when compiling the DLL project; just specify the LIB as a linker input. However, if you need to make use of the LIB code from within the DLL, you will need to #define DLLAPI as an empty macro; setting the symbol(s) to either dllexport or dllimport will generate an error or a warning, respectively.
There is some discussion of this problem on MSDN which was pretty useful. As it turns out, /OPT:NOREF is not particularly helpful in this case. /INCLUDE can work but it can be hard to automatically figure out what needs to be /INCLUDEd. There's unfortunately no silver bullet.
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/2aa2e1b7-6677-4986-99cc-62f463c94ef3