Lescha
asked on
DLL Questions Series, 2
This is the second part of the series.
The Overview can be found at:
https://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=10294044
The previous parts can be found at:
(1) https://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=10294050
Using Visual Studio (ver. 6), how do I make a program to use a DLL called MyDll.DLL? The program itself is a pair of text files, one called MyProg.CPP the other MyProg.H.
The expected answer is an algorithm constisting of actions of the kind:
Add so-and-so text to the so-and-so places in the file.
Use so-and-so options in the compiler/linker configuration.
Use so-and-so functions to link the DLL with the project (or to make the program call the DLL).
Etc.
For now, we shall assume that the files contain simple C++ functions and do not use MFC classes.
The Overview can be found at:
https://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=10294044
The previous parts can be found at:
(1) https://www.experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=10294050
Using Visual Studio (ver. 6), how do I make a program to use a DLL called MyDll.DLL? The program itself is a pair of text files, one called MyProg.CPP the other MyProg.H.
The expected answer is an algorithm constisting of actions of the kind:
Add so-and-so text to the so-and-so places in the file.
Use so-and-so options in the compiler/linker configuration.
Use so-and-so functions to link the DLL with the project (or to make the program call the DLL).
Etc.
For now, we shall assume that the files contain simple C++ functions and do not use MFC classes.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
For example.
-----Dll's header file.------
#ifndef In_SomeDll
#define SomeDllExport __declspec(dllexport)
#else
#define SomeDllExport __declspec(dllImport)
#endif
SomeDllExport int Increment(int i);
------Dll's source code-----
#define In_SomeDll
#include <SomeDll.h>
int Increment(in i)
{
return i + 1;
}
-------EXE's source code------
#include <SomeDll.h>
int X = increment(5); // X = 6.
-----Dll's header file.------
#ifndef In_SomeDll
#define SomeDllExport __declspec(dllexport)
#else
#define SomeDllExport __declspec(dllImport)
#endif
SomeDllExport int Increment(int i);
------Dll's source code-----
#define In_SomeDll
#include <SomeDll.h>
int Increment(in i)
{
return i + 1;
}
-------EXE's source code------
#include <SomeDll.h>
int X = increment(5); // X = 6.
I could never compete with Todd's lightning speed...
Let me just add that:
1) It is a good idea to use a DllMain() function. The stub generated by the "wizard" looks like this:
BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Customize as needed.
2) The DLL file is linked with the following switches:
/dll /out:"MyDll.dll"
Let me just add that:
1) It is a good idea to use a DllMain() function. The stub generated by the "wizard" looks like this:
BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Customize as needed.
2) The DLL file is linked with the following switches:
/dll /out:"MyDll.dll"
>> I could never compete with Todd's lightning speed...
Well, this one wasn't even close, you are more than 12 hours behind.
>> 2) The DLL file is linked with the following switches:
>>
>> /dll /out:"MyDll.dll"
If you set up the project as a DLL in VC you probably don't have to worry about these switches as then should be set automatically for you.
Well, this one wasn't even close, you are more than 12 hours behind.
>> 2) The DLL file is linked with the following switches:
>>
>> /dll /out:"MyDll.dll"
If you set up the project as a DLL in VC you probably don't have to worry about these switches as then should be set automatically for you.
>> Well, this one wasn't even close
Priorities...
>> If you set up the project as a DLL in VC [...]
Indeed. This is just what goes on "behind the screen".
Priorities...
>> If you set up the project as a DLL in VC [...]
Indeed. This is just what goes on "behind the screen".
ASKER
Thanks, quite finely tuned answers!
1) Is there any principal difference between the two ways of linking? Is one of them, say, faster and the other more economical?
2) Where, given a smth.dll do I get a smth.lib from? Isn't smth.lib a static, not dynamic, library, anyway?
1) Is there any principal difference between the two ways of linking? Is one of them, say, faster and the other more economical?
2) Where, given a smth.dll do I get a smth.lib from? Isn't smth.lib a static, not dynamic, library, anyway?
Implicit linking by far the easiest to use and most widely used. The programmer doesn't have to go to extra steps to call a function using implicit linking. They just call the function just like any othet function and the compiler/linker/and Os all work to make the call succeeed. With explicit linking, the program has to get a pointer to a function and call the function using the pointer. There are extra steps involved and the danger that the pointer will be invalid or NULL.
However, explicit linking is useful for cases where you don't have a .lib file for a DLL, of if you need to call a function that might not be available in all versions of a DLL.
>> given a smth.dll do I get a smth.lib from?
Usually the .lib is made when the .dll is linked. However if you have a .dll and not coorespondign .lib, there are utilities that can genereate the .lib from the .dll.
However, explicit linking is useful for cases where you don't have a .lib file for a DLL, of if you need to call a function that might not be available in all versions of a DLL.
>> given a smth.dll do I get a smth.lib from?
Usually the .lib is made when the .dll is linked. However if you have a .dll and not coorespondign .lib, there are utilities that can genereate the .lib from the .dll.
>> explicit linking is useful for cases where you don't have a .lib file for a DLL,
>> or if you need to call a function that might not be available in all versions of a DLL.
Or the DLL might not be available on all systems.
Another interesting feature is the /delayload option.
>> or if you need to call a function that might not be available in all versions of a DLL.
Or the DLL might not be available on all systems.
Another interesting feature is the /delayload option.
ASKER
What about this 'pragma' thing? I read about it in MSDN but can't connect it with the DLLs.
Also: __declspec(dllImport) is used with implicit linking (i.e. via the LIB file), right? What utilities are there to create LIB from DLL?
Another thing: does using LIB instead of DLL not go against the philosophy of DLLs? I thought LIB is a static library, or do I have it wrong?
Also: __declspec(dllImport) is used with implicit linking (i.e. via the LIB file), right? What utilities are there to create LIB from DLL?
Another thing: does using LIB instead of DLL not go against the philosophy of DLLs? I thought LIB is a static library, or do I have it wrong?
>> What about this 'pragma' thing?
#pragma comment(lib,"lib path and name")
links the program to the specified lib file.
>> __declspec(dllImport) is used with implicit linking
yes.
>> What utilities are there
>> to create LIB from DLL?
I don't know any by name.
>> I thought LIB is a
>> static library, or do I have it wrong?
No that is right. When you declare a function as external (meaning the function's code is not defined in the current translation unit) and call that function, the compiler places a "request" in the object code that the call code be generated at link time when the function's location is finally known. When the program is linked, the final code for the call must be generated. If no function is found to link to the program cannot be completed. So the static library satisfies the link request. it contains stub functions that the calls to DLL functions link to. There are nto real funcitons, just stubs that at 6 bytes long and contain data that the program loader will use to make the dynamic link (the data indicates which DLL function is to be called.) when the DLL is loaded, the stub is altered (fixed up) so it contains a jump instruction to the proper function in the DLL.. So a call to the DLL function goes to the stub and then jumps to the right location.
#pragma comment(lib,"lib path and name")
links the program to the specified lib file.
>> __declspec(dllImport) is used with implicit linking
yes.
>> What utilities are there
>> to create LIB from DLL?
I don't know any by name.
>> I thought LIB is a
>> static library, or do I have it wrong?
No that is right. When you declare a function as external (meaning the function's code is not defined in the current translation unit) and call that function, the compiler places a "request" in the object code that the call code be generated at link time when the function's location is finally known. When the program is linked, the final code for the call must be generated. If no function is found to link to the program cannot be completed. So the static library satisfies the link request. it contains stub functions that the calls to DLL functions link to. There are nto real funcitons, just stubs that at 6 bytes long and contain data that the program loader will use to make the dynamic link (the data indicates which DLL function is to be called.) when the DLL is loaded, the stub is altered (fixed up) so it contains a jump instruction to the proper function in the DLL.. So a call to the DLL function goes to the stub and then jumps to the right location.
search for 'implib'
ASKER
Thanks to all the Experts who participated in answering:
"nietod", "alexo".
Next part will be posted shortly.
"nietod", "alexo".
Next part will be posted shortly.
In the EXE's source code you need to declare any of the procedures or data that is experted from the DLL and that you wish to use in the EXE. These procedures/data must be declared as external, since they are not defined in the EXE, this can be done using the standard "extern" keyword, but instead it is usually done using the "_declspec(dllimport)" specification. For example a procedure defined in the DLL like
__declspec(dllexport) int Increment(int i)
{
return i + 1;
};
Would be declared like
__declspec(dllimport) int Increment(int i);
A varaible declared in an DLL like
__declspec(dllexport) int X = 5;
would be declared in the EXE like
__declspec(dllimport) int x;
Often DLL authors will create a .h file that defines all the exported items in the DLL, so the EXE can simply include this .h file and not contain the imported item declarations directly.
The DLL author can use conditional compilation so that the same .h file can be used when compiling the DLL itself. In this case conditional compilation is used so that __declspec(dllimport) is used when the .h is used in code that uses the DLL and __declspec(dllexport) is used when the .h is used in the DLL.
continues.