Getting symbols for explicitly loaded DLL from the application - c++

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.

Related

How to build with required `.dll` in Windows 10 Visual Studio

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.

How to call a function in DLL defined another project

I'd like to call a function in DLL (lets say foo function defined in a X project ). So DLL never knows the exact implementation of this foo function. But later I want to use this DLL in the X project (that contains the foo function).
When I try to compile the DLL, linker gives the "Unresolved external" error. How can I tell the compiler that foo function is defined in another project.
For example;
foo.cpp in DLL project
extern void foo();
void DLLFunction()
{
foo();
}
impl.cpp in X project
void foo()
{
//Do something
}
And if I can compile foo.cpp in the DLL project, I will use this DLL in the X Project.
If I understand the question correctly, you want to have a DLL, which imports a function from the executable it is linked against.
In general it is possible, but tricky, so first thing you should consider is if you really need to do that or if you can change the DLL function to e.g. accept a function pointer (which then does not require to import a symbol from executable into the DLL).
It is still possible to use symbol from executable in the DLL. It is possible to export a symbol (function) from the executable and use in the DLL (normally the same way you export from DLL, e.g. "__declspec(dllexport)" on Windows). However the tricky part is, that by default you need the dependency to link the particular object, i.e. in this case you'd need the DLL to link the executable and the executable to link the DLL, which is a cyclic dependency.
So you need to break the cyclic dependency. There are some possibilities:
Loading the DLL dynamically as a plugin - using dlopen() on Posix and LoadLibrary() under Windows. Then you do not need the DLL to build the executable, and you can link the EXE providing the symbol with the DLL.
The other way around - on Windows, you can dynamically import the exported symbol from the executable into the DLL (GetModuleHandle(), GetProcAddress()).
Allowing the DLL to be build with unresolved symbols. Then you build the DLL with the symbol unresolved, and build the EXE against the DLL. When executed, the executable will load the DLL and will provide the symbol.
To allow building the DLL with unresolved symbols:
In Linux GCC this is the default behaviour (shared objects do not enforce symbols to be resolved), unless you build with "-Wl,--no-undefined".
In Windows MSVC, you can ignore the unresolved symbols when building the DLL by providing the "/FORCE:UNRESOLVED" parameter to the linker. Note that on Windows/MSVC, after you build the EXE .lib file, you then need to rebuild the DLL again against that file to import the symbol.
What you can do is to instead of writing extern, you can load the DLL dynamically
e.g.
auto hd = LoadLibrary("YourDll.DLL");
typedef void(*userfunc)() ;
userfunc p = GetProcAddress(hd, "foo");
p();
Alt. link with the .lib file created when you built the DLL
discalimer: code for cleanup, error checks etc omitted.
If you are using a recent version of the Visual Studio IDE, you can simply reference it - Visual Studio will take care of the rest. To do that, right click on the "References" entry in your Solution Explorer for the project you want to link against your DLL. From there, select the other DLL project in your solution:
This will take care of all the linking required and saves you the trouble of changing your project settings if you rename your projects or change the name of the output-files.
If you don't have the other project in your solution you will have to stick with the regular static linking procedure:
Project Settings -> Linker -> General -> Additional Library Directories
Project Settings -> Linker -> Input -> Additional Dependencies
If you want to dynamically link against the DLL at runtime, you can use the method described by Andreas K.

Bridging unmanaged and managed classes

I have a native C++ class that is exported to a Win32 Dll:
class __declspec(dllexport) Manager { ... }
The Dll is created successfully. Let's call it Unmanaged.dll.
I want to use this class in a .Net application. Therefore, I decided to create managed C++ wrapper classes. So I created a new CLR class library where I set Unmanaged.dll as an input to the linker.
When compiling the managed dll I get the following error:
fatal error LNK1107: Invalid or corrupt file: cannot read at 0x318. (Unmanaged.dll in project ManagedBridge)
Both projects are set to compile to x64. DLL Export Viewer shows the class' constructor and methods. So the Dll seems to be fine.
Is there something I am missing?
You cannot pass a DLL to the linker, it has no idea what to do with it. A DLL is in general not suitable to help a linker determine that the DLL contains the functions you call. Exports from a DLL can be a number of a name. It being a number (an "ordinal") is a problem, the linker will not know how to map the number to the identifier name. And the name does not have to match either, names are commonly simplified with their name decoration removed.
You must instead tell the linker about the DLL's import library. Which has more information, including the ordinal to name mapping and the original decorated name that the compiler used. The import library is a .lib that was created when you linked the DLL. You will find it back in the DLL project's build directory. Add its path to the linker's Additional Dependencies setting.

utilizing a static library to create an import library

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.

Dynamic linking in Visual Studio

I have to link dynamically with OpenSSL libeay32.dll.
I'm writing native c++ console application using Visual C++ Express 2008.
I'm including a header evp.h from OpenSSL distribution. Building and...:
error LNK2001: unresolved external symbol _EVP_aes_256_cbc
error LNK2001: unresolved external symbol _EVP_DecryptInit
error LNK2001: unresolved external symbol _EVP_CIPHER_CTX_init
How to make calls to libeay32.dll methods? I don't know where to specify it's filename
There is probably a .lib file you also need to add to your compiler's linker input. Check the documentation for the library you're using.
Try using Win32 API's LoadLibrary function, the following link might be of some help :example
if your application need to be able to run without the existence of OpenSSL, use dynamic linking with explicit run-time linking and handle the cases when the DLLs are not around (e.g. by changing your application's behavior / switching to other libraries).
I recently found a nice examples on this:
Google Gears WinCE Geolocation API
itsutils
if your application may only run if the OpenSSL exist in the environment (or you ship the DLL), use implicit run-time linking.
For MSVC, the simplest is to add #pragma comment(lib,"libeay32.lib") in your source code (You will probably need the .lib stub to be produced by the same compiler you use)
if your application need to be independent of the environment. Link OpenSSL statically (also uses .lib).
Note that there are 2 kinds of .lib. The first is used for dynamic but implicit linking, second is for static linking. The one for dynamic implicit linking contains stubs that load the DLL for you whereas the one for static linking contain the actual implementation.
In the project properties, configuration properties, linker, input - add the library name under "additional dependencies".
[Note, this will actually STATICALLY link with the library. If you truly want to load the library dynamically you will need to call LoadLibrary() on the DLL and then get function pointers for the functions you need using GetProcAddress().
See for example
http://msdn.microsoft.com/en-us/library/ms886736.aspx
and
http://msdn.microsoft.com/en-us/library/ms885634.aspx
If you are calling a method from the dll, you can use explict dynamic linking method.
Mistake: you are including a header evp.h from OpenSSL distribution dll to your prohject
As you are linking dynamically, no need to include .h from A DLL to your project.
You can call by following method:
LoadLibrary("libeay32.dll"); /* syntax: */
Declare a function pointer pointing to the function you want to call.
For eg.
Let your libeay32.dll has an exported function: int add(int x, int y);
Then to call it in your project declare a function pointer and then call the method add as follows:
typedef int (*AddfnPtr)(int num1, int num2);
int num1 = 2, num2 = 3 ;
HMODULE handle = NULL;
handle = LoadLibrary("libeay32.dll");
if (handle != NULL)
{
AddfnPtr addfnptr = (AddfnPtr)GetProcAddr(handle, NULL);
if (addfnptr != NULL)
{
int res = addfnptr(num1,num2);
cout << "res = "<<res;
}
}