I'm trying to build a project. I have a.lib file that I need to use in my project. I know that there are two ways to use this lib:
add it using #pragma comment(lib, "a.lib")
add it to linker dependencies Configuration Properties -> Linker -> Input -> Additional Dependencies
Now, a.lib uses StackWalk64 function DbgHelp. This library is supplied as DbgHelp.lib and DbgHelp.dll. I know that I can use it as a lib using two ways listed above. But what if I don't want to include it into my project and want to use DbgHelp.dll, how can I do that in Visual Studio?
If you want to call a function that is within a DLL, but don't want to link to the LIB file that imports these functions for you, then you can use LoadLibrary and GetProcAddress. (Though if you have the import library and can link to it, why do you want to load these functions manually?)
IF YOU HAVE THE DbgHelp.lib IMPORT LIBRARY, USE IT! LOADING FUNCTIONS MAUNALLY IS ERROR-PRONE IF NOT DONE RESPONSIBLY. USE WITH CAUTION!
// Type definition for a function pointer that can call the function
typedef BOOL (WINAPI *StackWalk64_func)
(
DWORD,
HANDLE,
HANDLE,
LPSTACKFRAME64,
PVOID,
PREAD_PROCESS_MEMORY_ROUTINE64,
PFUNCTION_TABLE_ACCESS_ROUTINE64,
PGET_MODULE_BASE_ROUTINE64,
PTRANSLATE_ADDRESS_ROUTINE64
);
// Within a function . . .
HMODULE hDbgHelpDll = LoadLibrary(TEXT("DbgHelp.dll"));
if (hDbgHelpDll == NULL)
{
// handle error and return
}
StackWalk64_func funStackWalk64
= (StackWalk64_func)GetProcAddress(hDbgHelpDll, "StackWalk64");
if (funStackWalk64 == NULL)
{
// handle error and return
}
// funStackWalk64 is valid and ready to use
Now you can call funStackWalk64 like the function StackWalk64, and pass the function pointer around the place. When you're done using the library, you should free the module handle:
FreeLibrary(hDbgHelpDll);
Please read up: http://www.learncpp.com/cpp-tutorial/a1-static-and-dynamic-libraries/
Implicit Linkage with an import library (using .lib)
In this case the static-library is an "import library", which automates the process of determining the effective functions in the DLL. This is called implicit dynamic linkage.
Explicit Linkage
If you don't want to use the import library you have to determine all functions by yourself, create corresponding pointers to the addresses of the procedures and use them after that.
Usually there's some InitDLL() function in your client code, which does this.
See: https://msdn.microsoft.com/de-de/library/64tkc9y5.aspx
The "GetProcAddress"-function can be used to obtain a handle to the function and call it.
This is called explicit dynamic linkage and requires also the calls to LoadLibrary() and FreeLibrary() on Windows.
More Info: http://www.equestionanswers.com/dll/what-is-implicit-and-explicit-linking-in-dynamic-loading.php
Explicit Linkage on Linux
For linux/unix things work differently. If you want to read up: http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
Usually (and in Visual C++ specifically,) the lib file that comes with a dll is what is called an "import library". It means that the library has no actual function bodies in it; it is just there to appease the linker and instruct it to generate an EXE (or DLL) that would use the first dll at load time.
It is so in this case too. Since you don't have access to the source code for DbgHelp so that you can build it as a real static library, you need to make do with the small import library at link time and the dll file at load/run time.
Note: the whole linking and dynamic linking concepts and mechanisms are obviously a lot more complex than what I have room here to discuss. So, the explanation above is quite narrow and specific to your question.
Related
I am modifying my application so that it can explicitly load a DLL (through the Windows API) and call some functions from the DLL. But I need to be able to call some application's functions from the DLL too. I can only provide header files of the functions to the DLL. But I am getting the LNK2019 'unresolved external symbol' error.
Is my idea even feasible?
So you found a way to do this, however you should also ask yourself whether you should do it.
If your executable depends on the DLL then the DLL should not depend on that executable. This is not just a question about principles but also about avoiding future problems.
The way you could achieve the calls from the DLL to the executable is to define a function-pointer type and a setter in the DLL's headers:
typedef void aCallbackType(void);
void setMyCallback(aCallbackType* Cb);
In setMyCallback the DLL stores that function-pointer to later call it.
Then the executable can define a function and give that to the DLL:
void myCallback(void) { }
void myProgram(void) {
setMyCallback(myCallback);
}
Thank you #AdrianMole for solving my problem! To resolve the external symbols in the DLL you'll need to create an import library of the EXE. In Visual Studio 2017, this can be done by going to the project properties. Go to Linker → Advanced and set the Import Library setting to the path and name you want. (For example: $(TargetDir)\myimportlibrary.implib). Then, go to the the DLL project properties → Linker → Input and add the import library to the Additional Dependencies setting.
I am looking for a clean way to explicitly load library. Most often, I have a LIB and DLL pair so the LIB will handle all the "load stuff" and I can directly call the function in the dll. When doing this explicitly, I need to do sort of the following:
HMODULE libA = LoadLibrary("dllA.dll"); // NULL if load failed
HMODULE libB = LoadLibrary("dllB.dll"); // NULL if load failed
void (*functionA)(void) = libA ? GetProcAddress(libA,"functionA"):NULL;
void (*functionB)(void) = libB ? GetProcAddress(libB,"functionB"):NULL;
It will be messy if the LoadLibrary() and GetProcAddress() are found all over my code when I need to call function in DLL. I would like to know if there is a clean way such that I can write all the handling within 1-2 files and call the functions as if I am loading the library implicitly through LIB and DLL pair.
Indeed there is a way to get all the implicit linking convenience, while still being able to gracefully handle both library load as well as symbol lookup failures. Visual Studio offers Linker Support for Delay-Loaded DLLs, that give user code the ability to hook into the loader, and implement arbitrary recovery strategies for unavailable symbols (e.g. by returning a no-op stub). This makes it possible to consolidate all failure handling into a single place.
Write a pure interface to the external functions you need. (Platform dependent)
Provide an implementation class (for you platform). For your Windows implementation load the DLL, get the procedure address initially.
Than when the interface function need to be called, the class routes the call into the loaded DLL.
Use an similar way for other platforms.
This is nothing else than using of delay-loaded DLLs. It is just a manual solution. But the approach of using an interface allows you a real platform dependent solution.
I am interested in using my static lib to create a dll (implicitly linking). which means I need to (in vs2008)
create a dll project that should generate the following:
header file (which have export function declarations. These are simple wrappers to actual functions in the static lib using __declspec(dllexport) which are in the .cpp )
import lib which will be made as a result of creating the dll
the actual dll which is created.
I have made a test program that will utilize the above dll(including the import lib/header files) to test it.
in this I have included all the three items. now the exe compiles/links without issue.
however in the main.cpp when i call the exported functions (with the associated __declspec(dllimport) call it never seems to execute. I am uncertain why this is?
Its almost like the even though the exe can see the exported function in in the dll...the dll cannot call on the code that is in the static lib?
i just cannot answer why my exe can't see the code in the static lib? do i need an archiver/librarian for vs2008 to include all those obj files as part of the import lib?
I am at a loss and am not sure how to test this?
other than just making my static lib directly into a dll. I wanted to try this method. I know i am missing something...i have read all over the place and i am just stuck. There were some threads here that had some people posting something similar but i can't seem to get it. please be as detailed as possible as I am new to this. thanks again.
update 1:
ok so currently i added the extern line to the function prototype and now it sees the exported function from the dll. however, now the only issue left is that:
i can't invoke the function that this exported function (aka wrapper) is trying to call. which happens to be in the static library. how should my exe get visibility to that static library function. I know it can be done because I think there was one other person on this board who was able to make this work.
update 2: my setup is exactly like this questioner...
How to force inclusion of an object file in a static library when linking into executable?
but i am not using explicit linking. i am using implicit linking. my real issue is how to call a static lib function in my dll wrapper which is exported to the exe?
If the app and DLLs are MFC app/dlls, then make sure that the application and all dlls are either "Debug" versions or "release" versions and not a mix.
When I want to call some Windows function, like MessageBox I can import it from user32.dll and call (with LoadLibrary and GetProcAddress). But there is also a static library that Visual C++ uses, so I don't need to manually load DLLs and functions. How do they work? Do they contain wrappers that call LoadLibrary/GetProcAddress every time I call a function?
The "static library" that you're referring to is actually an import library. This type of library contains records that tell the linker which library each function actually exists in, and doesn't contain any code itself. The linker creates import records in the executable, which the loader resolves at load time. This fixes up the addresses used at runtime so your code doesn't need to explicitly call LoadLibrary and GetProcAddress.
No, they just allow you to use static linking with DLLs. The executable file contain a list of functions that it needs from other DLL files, so when the executable file is loaded the loader parses this list and resolves each function with LoadLibrary and GetProcAddress, saving result to a static table (IAT, Imported Address Table). This is done only once. There is also the notion of "delayed load" of DLL, that will resolve the address only when the function is call for the first time, but it's rarely used.
In this way the lib file for a DLL contains just information needed to build that list (names of exported functions).
I have some statically compiled libraries (.lib) that I use in my project, which is written in C++ and built on both Windows and Linux. At my project's entry-point to these libraries, I use just one or two functions from the 'main' library in the static library suite, really (but I'm sure that these functions call many others in the other libraries in the suite).
I would ideally like to instead have a suite of dynamically linked libraries (DLLs) that wraps around each of the libs in the static lib suite; I've read/heard that the way to do this on Windows (e.g., Visual Studio 2005/2008/2010) is to "create a wrapper DLL" with some exposed functions calling the underlying static library functions. I would very much appreciate if someone can give me some detailed step-by-step including possibly some snippets, of how to go about doing this in MS Visual Studio 2005/2008/2010. I am sure some of you may already be doing this on a day-to-day basis; your experience is very much appreciated.
Edit:
For the benefit of others like myself, I am posting the first 'useful' link I found:
http://tom-shelton.net/index.php/2008/12/11/creating-a-managed-wrapper-for-a-lib-file/
"Convert a library to another library type" seems easy, but it is not. There is no straight-forward step-by-step way to do this because C++ and DLLs do not play well together at all, and your code will need to be adapted to support a DLL interface.
A concise way to describe the problem is this:
A .lib's interface is C++
A .dll's interface is C
Thus, a DLL's interface simply doesn't support C++ and you need to be clever to make it work - this is why the ambiguous existing answers.
One standard way is via COM, which means building an entire COM wrapper for the library, complete with class factory, interfaces, objects, and using BSTR instead of std::string. I would guess is not practical.
Another solution is to create a C interface for your C++ library which is DLL-safe. That means basically creating a winapi-style interface, which again is probably not practical or defeats the purpose of using your library at all. This is what #David Heffernan suggests. But what he doesn't address is how you must change your code to be DLL-compatible.
An important but subtle problem is you cannot pass ANY templated C++ objects across DLL boundaries. This means passing std::string in or out of a DLL function is considered unsafe. Each binary gets its own copy of the std::string code, and there's no guarantee that they will happen to play nicely with each other. Each binary (potentially) also gets its own copy of the CRT and you will mess up internal state of one module by manipulating objects from another.
Edit: You can export C++ objects in MSVC using __declspec(dllexport) and importing them using __declspec(dllimport). But there are a lot of restrictions on this and subtleties that cause problems. Basically this is a shortcut for getting the compiler to create a cheap C-style interface for your exported class or function. The problem is it doesn't warn you about how much unsafe stuff is happening. To reiterate:
If there are ANY templated symbols crossing DLL bounds, it is not safe (std::* for example).
Any objects with CRT-managed state should not cross DLL bounds (FILE* for example).
If you do not care about interface adaptation at all, you can export symbols from a static .lib to a .dll fairly easily. The trick is, you do not use Visual Studio GUI or projects at all, but just the linker (link.exe).
With this method, C symbols will remain C symbols and C++ symbols will remain C++ symbols. If you need to change that, you need to write wrapper code (e.g. extern C interfaces). This method simply presents existing symbols from the .objs in the .lib as official exports from the DLL.
Assume we have a .lib compiled from a source TestLib.c
#include <stdio.h>
void print(char* str)
{
printf("%s\n", str);
}
int add(int a, int b)
{
return a + b;
}
We compiled this into a static lib TestLib.lib. Now we wish to convert TestLib.lib to TestLibDll.dll (the base name should not be the same or you will get issues with the link output since the linker also creates DLL link .lib). To do this, we use link.exe outside Visual Studio GUI. Launch the "x64 Native Tools Command Prompt for Visual Studio xx" to get a cmd with the toolchain in path. (If you need 32 bit version, use x86 Native Tools instead). Change to the folder with TestLib.lib (e.g x64\Release). Then run:
link /DLL /EXPORT:add /EXPORT:print /OUT:TestLibDll.dll TestLib.lib
This should produce TestLibDll.dll. (The linker may complain a bit about there being no .obj, but you can ignore this.) The exports are:
dumpbin /exports TestLibDll.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30040.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file TestLibDll.dll
File Type: DLL
Section contains the following exports for TestLibDll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00001080 add
2 1 00001070 print
We have successfully exported the functions.
In the case there are many functions, using /EXPORT is tedious. Instead make a .def file. For our example, here is TestLibDll.def:
LIBRARY TestLibDll
EXPORTS
print #1
add #2
The linker is then run as
link /DLL /DEF:TestLibDll.def /OUT:TestLibDll.dll TestLib.lib
This example uses x64 C symbols, which makes it straightforward. If you have C++ symbols, you need to provide the mangled version of the symbol in the /EXPORT argument or in the def file. For more complex situations than a single static lib, you may need to provide more link libraries on the command line and/or /LIBPATH args to point to link library folders.
Again, this method is only for exporting symbols verbatim from a static library. I personally used it to create a DLL to be loaded in Python with ctypes for a closed source static library. The advantage is you don't need to write any wrapper code or create any additional VS projects at all.
Note: the accepted answer provides a good discussion of pitfalls regarding C++ DLL interface and why C wrappers are a good idea. I did not focus on that here, only on the mechanics of getting the symbols to be exported to the DLL. Using a C interface to DLL if possible remains good advice.
This was a little big to add as a comment to tenfour's response...
If you want to still maintain a C++ API when using the DLL wrapper, you can put C++ to C conversion functions in the header file. This ensures that only C compatible data types ever cross the DLL boundary.
As an example
//MyDLL.h
class MyDLL {
public:
...
int Add2ToValues(std::vector<int>& someValues) {
int* cValues = new int[someValues.size()];
memcpy(cValues, &someValues[0], someValues.size() * sizeof(int));
int retVal = Add2ToValues_Internal(cValues, someValues.size());
someValues.assign(std::begin(cValues), std::end(cValues));
delete [] cValues;
return retVal;
}
private:
int Add2ToValues_Internal(int* valuesOut, const int numValues);
};
//MyDLL.cpp
int MyDLL::Add2ToValues_Internal(int* values, const int numValues)
{
for(int i = 0; i < numValues; ++i) {
values[i] += 2;
}
return 0;
}
One catch I ran into when doing these wrappers is that you must allocate and deallocate any memory within the header file. Since the header file will be compiled by the application that is using your library, it will use the CRT for whatever compiler you are using to build your application. All interaction with the DLL uses C, so you won't run into any runtime mismatches and all memory is allocated and freed either entirely within the DLL or entirely within the application so you don't have any cross DLL memory management issues either. In the example, I both allocated and deallocated in the header. If you need to allocate data in the _Internal function, you'll need to also add a function that allows you to free that memory within the DLL. Once inside of the _Internal functions, you are free to use as much C++ as you want.