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.
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 cannot get a DLL to link, that needs a class exported from the app this DLL will be used with. Visual Studio 2008, Windows 7.
I had a small sample DLL compiling (the default MSFT DLL project actually), and the app can use LoadLibrary() and GetProcAddress() on it correctly. I'm experienced with dllimport/dllexport. Using dumpbin /exports was critical to discover the mangled names to use with GetProcAddress() (MSFT's default empty DLL includes a sample function without extern "C") but this is a solved problem.
The next step was to have the app export a class that the DLL will need to subclass. I do the dllimport/dllexport #define's in the reverse sense from usual: a special symbol when the app is compiled tags the class with dllexport and non-app code (such as the DLL) using that header, without the special symbol, gets a dllimport spec. dumpbin /exports on the .exe file shows exactly this class's (mangled) symbols being exported, and no others, as expected.
The next step was to have the DLL include the header and create an object of the exported object's type (as a baby-step towards actually subclassing it). Compiles fine, but linker shows error:
DynTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Test::Test(class Toast*,double)" (??0Test##QAE#PAVToast##N#Z) referenced in function "public: __thiscall CDynTest::CDynTest(void)" (??0CDynTest##QAE#XZ)
OK, that didn't surprise me, as I know on WIN32 I need to supply DLL's at link time to make a DLL, unlike my usual Unix. Since Windows seems to treat DLLs and executables a bit similarly, I tried adding the .exe at Properties->Configuration Properties->Linker->Input->Additional Dependencies. That gets an error that looks like LINK.EXE didn't auto-detect that it was being given an .exe:
T:\mypath\MyBinary.exe : fatal error LNK1107: invalid or corrupt file: cannot read at 0x348
I then tried adding instead the object file that defines this class... That seems to be understood by the linker, and is probably successfully satisfying the DLL's need to link, but now shows a myriad of other symbols this file depends upon.
So I've considered refactoring the app such that most of it is in a DLL or LIB, just so I can supply that as an "Additional Dependencies" to the DLL I'm actually worried about. But this seems to be draconian. Is that my only option?
Invoking dumpbin /exports gives you a list of mangled names of exe exports. You need to create a module definition file (.def) containing these names:
EXPORTS
#d3d_some_fancy_mangedled_method_1
#d3d_some_fancy_mangedled_method_2
...
Notice that it is basically dumpbin output with first columns removed.
Then you use lib tool to generate export library from module definition file:
LIB /DEF:prog.def /NAME:prog.exe /MACHINE:x86
Finally you link generated export library prog.lib into your application. /MACHINE option should match to your executable. Notice that you don't need to link or anyhow use program executable to link it, only export library is used.
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.
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.
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;
}
}