Board index » cppbuilder » DLL and Forms

DLL and Forms


2003-11-21 01:16:07 PM
cppbuilder60
Here's what I'm trying to accomplish. I have a main form which uses other
forms. I want to include these other forms in dll's. That way when I
update the program I can just transfer a small dll file that contains the
modifications to the form...I won't have to update the entire program.
I Have 3 projects. All projects have these settings: Use Dynamic RTL is
checked and Build with Runtime Packages is Checked.
When trying to compile and run the main application I get the following
errors:
[Linker Error] Unresolved external '_CreateTfrmOne' referenced from F:\DLL
FORMS\MAINFORM.OBJ
[Linker Error] Unresolved external '_FreeTfrmOne' referenced from F:\DLL
FORMS\MAINFORM.OBJ
[Linker Error] Unresolved external 'TfrmTwo::' referenced from F:\DLL
FORMS\MAINFORM.OBJ
[Linker Error] Unresolved external '__fastcall
TfrmTwo::TfrmTwo(Classes::TComponent *)' referenced from F:\DLL
FORMS\MAINFORM.OBJ
The main project is called DLLForms...I simply used new application. It has
one form called TfrmMain. Here are the header and .cpp files
//----------------.h
file-----------------------------------------------------------
#ifndef MainFormH
#define MainFormH
//--------------------------------------------------------------------------
-
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "OneForm.h"
#include "TwoForm.h"
//--------------------------------------------------------------------------
-
class TfrmMain : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TfrmMain(TComponent* Owner);
};
//--------------------------------------------------------------------------
-
extern PACKAGE TfrmMain *frmMain;
//--------------------------------------------------------------------------
-
#ifdef __DLL__
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
extern "C" TfrmOne* EXPORT CreateTfrmOne();
extern "C" void EXPORT FreeTfrmOne(TfrmOne* Value);
extern "C" TfrmTwo* EXPORT CreateTfrmTwo();
extern "C" void EXPORT FreeTfrmTwo(TfrmTwo* Value);
//--------------------------------------------------------------------------
-
#endif
//--------------------------------------------------------------------------
-
//-----------------------.cpp
file----------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "MainForm.h"
//--------------------------------------------------------------------------
-
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmMain *frmMain;
//--------------------------------------------------------------------------
-
__fastcall TfrmMain::TfrmMain(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------
-
void __fastcall TfrmMain::Button1Click(TObject *Sender)
{
TfrmOne* frm = NULL;
try
{
if(!LoadLibrary("DLL1.dll"))
{
frm = CreateTfrmOne();
frm->ShowModal();
}
}
__finally
{
FreeTfrmOne(frm);
FreeLibrary("DLL1.dll");
}
}
//--------------------------------------------------------------------------
-
void __fastcall TfrmMain::Button2Click(TObject *Sender)
{
TfrmTwo* frm = NULL;
try
{
if(!LoadLibrary("DLL2.dll"))
{
frm = CreateTfrmTwo();
frm->ShowModal();
}
}
__finally
{
FreeTfrmTwo(frm);
FreeLibrary("DLL2.dll");
}
}
//--------------------------------------------------------------------------
-
As you can see I simply trying to create an instance of class derived from
TForm depending on which button the user pressed.
I have created 2 other projects using file->new and then selecting DLL
Wizard. With the C++ option checked, Use VLC checked, and multi threaded is
checked by default. I have made no modifications to the code generated. My
projects are called DLL1 and DLL2. To each of these projects I have added
a new form called TfrmOne and TfrmTwo Respectively.
Here is DLL1's code for the .h nothing has been modified to .cpp file for
this form...it just contains the constructor.
//--------------------------------------------------------------------------
-
#ifndef OneFormH
#define OneFormH
//--------------------------------------------------------------------------
-
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//--------------------------------------------------------------------------
-
class TfrmOne : public TForm
{
__published: // IDE-managed Components
private: // User declarations
public: // User declarations
__fastcall TfrmOne(TComponent* Owner);
};
//--------------------------------------------------------------------------
-
extern PACKAGE TfrmOne *frmOne;
//--------------------------------------------------------------------------
-
#ifdef __DLL__
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
extern "C" TfrmOne* EXPORT CreateTfrmOne()
{
return new TfrmOne(Application);
}
extern "C" void EXPORT FreeTfrmOne(TfrmOne* Value)
{
delete Value;
}
//--------------------------------------------------------------------------
-
#endif
//--------------------------------------------------------------------------
-
Here is DLL2's code for the .h nothing has been modified to .cpp file for
this form...it just contains the constructor.
//--------------------------------------------------------------------------
-
#ifndef TwoFormH
#define TwoFormH
//--------------------------------------------------------------------------
-
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//--------------------------------------------------------------------------
-
class TfrmTwo : public TForm
{
__published: // IDE-managed Components
private: // User declarations
public: // User declarations
__fastcall TfrmTwo(TComponent* Owner);
};
//--------------------------------------------------------------------------
-
extern PACKAGE TfrmTwo *frmTwo;
//--------------------------------------------------------------------------
-
#ifdef __DLL__
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
extern "C" TfrmTwo* EXPORT CreateTfrmTwo()
{
return new TfrmTwo(Application);
}
extern "C" void EXPORT FreeTfrmTwo(TfrmTwo* Value)
{
delete Value;
}
//--------------------------------------------------------------------------
-
#endif
//--------------------------------------------------------------------------
-
How do I get rid of the unresolved externals? When an automatic updater
program is ran and a new dll is saved onto the client machine I want the
main application or the TfrmMain to be able to load the modified dll's and
display the new TfrmOne and TfrmTwo forms.
Maybe I'm going about this entirely the wrong way...if so please direct me
to an easier way of accomplishing this task. I don't really want the
TfrmOne and TfrmTwo to be staticlly linked...I want them to be loaded during
runtime upon starting the application in case changes have been made to DLL1
and DLL2.
Sorry for such a long post :)
 
 

Re:DLL and Forms

"Junk Mail" < XXXX@XXXXX.COM >wrote in message
Quote
When trying to compile and run the main application I get
the following errors:
Sounds like you never declared __DLL__ in your DLL projects, thus the
functions being complained about are never being exported correctly. That
would explain why they are unresolved. __DLL__ is *not* a conditional that
is added to new DLL projects automatically, so you will have to add it to
the project's Conditionals list manually.
Gambit
 

Re:DLL and Forms

Quote
Sounds like you never declared __DLL__ in your DLL projects, thus the
functions being complained about are never being exported correctly. That
would explain why they are unresolved. __DLL__ is *not* a conditional
that
is added to new DLL projects automatically, so you will have to add it to
the project's Conditionals list manually.
For my 2 dll projects I went to project->options->Directories and
conditionals
My conditional defines looks like this for both projects
_DEBUG;__DLL__
For my main project my conditional defines looks like
_DEBUG
I still get the following linker errors
[Linker Error] Unresolved external '_CreateTfrmOne' referenced from F:\DLL
FORMS\MAINFORM.OBJ
[Linker Error] Unresolved external '_FreeTfrmOne' referenced from F:\DLL
FORMS\MAINFORM.OBJ
[Linker Error] Unresolved external 'TfrmTwo::' referenced from F:\DLL
FORMS\MAINFORM.OBJ
[Linker Error] Unresolved external '__fastcall
TfrmTwo::TfrmTwo(Classes::TComponent *)' referenced from F:\DLL
FORMS\MAINFORM.OBJ
Am I doing something else wrong?
 

{smallsort}

Re:DLL and Forms

"JunkMail" < XXXX@XXXXX.COM >wrote in message
Quote
try
{
if(!LoadLibrary("DLL1.dll"))
{
frm = CreateTfrmOne();
frm->ShowModal();
}
}
__finally
{
FreeTfrmOne(frm);
FreeLibrary("DLL1.dll");
}
You are dynamically loading the DLL. Am I right in assuming then that you
are *not* adding the DLL's .LIB files to the main project? If not, then
that would account for the errors you are seeing as well. If you are
dynamically loading a DLL, then you should *not* be using
__declspec(dllimport) at all. Using __declspec(dllimport) will only work if
you are statically linking to the .LIB files. Otherwise, you should get rid
of the 'extern' declarations from your main app altogether and use
GetProcAddress() instead, ie:
typedef TfrmOne* (*CREATETFRMONE)();
typedef void (*FREETFRMONE)(TfrmOne*);
HINSTANCE hDll = LoadLibrary("DLL1.dll");
if( hDll )
{
CREATETFRMONE lpCreateTFrmOne = (CREATETFRMONE)GetProcAddress(hDll,
"_CreateTFrmOne");
FREETFRMONE lpFreeTFrmOne = (FREETFRMONE)GetProcAddress(hDll,
"_FreeTFrmOne");
if( lpCreateTFrmOne && lpFreeTFrmOne )
{
try
{
frm = lpCreateTfrmOne();
try {
frm->ShowModal();
}
__finally {
lpFreeTfrmOne(frm);
}
}
catch(Exception&){}
}
FreeLibrary(hDll);
}
Gambit
 

Re:DLL and Forms

Quote
You are dynamically loading the DLL. Am I right in assuming then that you
are *not* adding the DLL's .LIB files to the main project? If not, then
that would account for the errors you are seeing as well.
Yes my intentions are to dynamically load them in so when my auto update
program downloads a new .dll it will load them and the changes will take
affect
Quote
If you are dynamically loading a DLL, then you should *not* be using
__declspec(dllimport) at all. Using __declspec(dllimport) will only work
if
you are statically linking to the .LIB files. Otherwise, you should get
rid
of the 'extern' declarations from your main app altogether and use
GetProcAddress() instead, ie:
Was unaware of this.
Quote
typedef TfrmOne* (*CREATETFRMONE)();
typedef void (*FREETFRMONE)(TfrmOne*);

HINSTANCE hDll = LoadLibrary("DLL1.dll");
if( hDll )
{
CREATETFRMONE lpCreateTFrmOne =
(CREATETFRMONE)GetProcAddress(hDll,
"_CreateTFrmOne");
FREETFRMONE lpFreeTFrmOne = (FREETFRMONE)GetProcAddress(hDll,
"_FreeTFrmOne");

if( lpCreateTFrmOne && lpFreeTFrmOne )
{
try
{
frm = lpCreateTfrmOne();
try {
frm->ShowModal();
}
__finally {
lpFreeTfrmOne(frm);
}
}
catch(Exception&){}
}

FreeLibrary(hDll);
}


Gambit
Thanks that worked.
BTW what does the lp stand for in lpCreateTfrmOne?
CREATETFRMONE lpCreateTFrmOne = (CREATETFRMONE)GetProcAddress(hDll,
"_CreateTFrmOne");
Also what happens if I overload the function passed into GetProcAddress?
For example CreateTfrmOne(TForm* frm) or something like that...what
determines the name to use in the getProcAddress? I noticed that there is
an underscore in the name added so there must be same naming convention
rules going on.
 

Re:DLL and Forms

"JunkMail" < XXXX@XXXXX.COM >wrote in message
Quote
BTW what does the lp stand for in lpCreateTfrmOne?
It is just a variable name, you can name it anything you want. I like to
use "lp" for "long pointer" in my names whenever I'm declaring function
pointers.
Quote
Also what happens if I overload the function passed into GetProcAddress?
Typically, you can't overload functions exported from DLLs. However, if you
were to get rid of the 'extern "C"' from your exported functions, then their
names will be mangled, ie:
CREATETFRMONE lpCreateTFrmOne = (CREATETFRMONE)GetProcAddress(hDll,
"_CreateTFrmOne@qt");
If you have two functions that have the same name but different parameter
lists, then the mangling will likely be different for each function (as long
as the overall parameter list is of different sizes), ie:
CREATETFRMONE lpCreateTFrmOne1 = (CREATETFRMONE)GetProcAddress(hDll,
"_CreateTFrmOne@qt");
CREATETFRMONE lpCreateTFrmOne2 = (CREATETFRMONE)GetProcAddress(hDll,
"_CreateTFrmOne@qvf");
In that regard, that is about the only way DLLs can export overloaded
functions. However, in practice, that is not a good design in general. If
you need two functions, then you should keep them separate, giving them
different names that better reflect what each function actually does, for
example CreateTFrmOne() and CreateTFrmOneParam() or something like that.
Quote
what determines the name to use in the getProcAddress?
You have to use the name that is listed in the DLL's exports table, which
the compiler generates for the DLL based on the actual names of the exported
functions and their calling conventions. The easiest way to know what those
names actually are is to use Builder's TDUMP utility. Or, if you code the
functions to use both 'extern "C"' and the __stdcall convention, then no
mangling or underscore will be present at all, and the stored name in the
exports table will be the same as just the actual function name (ie,
"CreateTFrmOne").
Quote
I noticed that there is an underscore in the name added so there
must be same naming convention rules going on.
The underscore is caused by not specifying any calling convention for your
exported functions, so the compiler used the default convention of __cdecl,
which states that functions using that convention must have underscores in
their symbol names. Underscores are separate from name mangling, which you
stripped off when you used 'extern "C"'. If you look at the examples above,
name mangling refers to just the"@" symbol and everything after it in the
function names that were passed to GetProcAddress().
Although it is not strictly required, most exported DLL functions will
explitically use the __stdcall convention instead. It just makes the DLL
more compatible with more compilers, if that were your intention. If the
DLLs are only your own private use, then you can continue using __cdecl if
you want.
Also note that whatever convention the DLL actually uses, the function
pointer in the main app must be declared to use the same convention as well,
or else the compiler will generate incorrect machine code for the main app
when calling the DLL functions, which will potentially (and likely) corrupt
the stack.
Gambit
 

Re:DLL and Forms

Instead of Dynamically loading the dll's in using code and using
LoadLibrary, GetProcAddress, etc. I found an option that might work but
whant your opinion.
Can I simply use the dllimport as I was in the previous code and then in my
project options under advanced linker Dlls to delay-load just put my DLL's
in there? Any advantage/disadvantage to using this method?
If I need to download a dll with a higher version can I still use the
FreeLibrary method on this dll so that I can copy the something.dll to disk?
Which brings me to another question How do I determine if a .dll or anyother
file for that matter is in use and the contents can not be written to?
The scheme I have come up with my exe for being updated is to have a
separate an overwrite.exe program the main.exe creates a new process
calling the overwrite.exe if main.new exists. Then main.exe closes.
Overwrite waits until main.exe is closed and then writes the new main.exe
and then starts main.exe up again.
I suppose I could use the scheme for my dll updating but problem is more
than app could be using the .dll Any suggestions or helpfull pointers on
this process?
 

Re:DLL and Forms

"JunkMail" < XXXX@XXXXX.COM >wrote in message
Quote
Can I simply use the dllimport as I was in the previous code and
then in my project options under advanced linker Dlls to delay-load
just put my DLL's in there?
The delay-load mechanism uses the Load/FreeLibrary() and GetProcAddress()
functions internally.
Quote
If I need to download a dll with a higher version can I still use
the FreeLibrary method on this dll so that I can copy the
something.dll to disk?
You should not call FreeLibrary() directly for a delay-loaded DLL. You need
to use the __FUnloadDelayLoadedDLL() function instead, so that the
delay-load mechanism can clean up after itself and prepare to dynamically
load the DLL again the next time you try to access it without restarting the
program first.
Quote
How do I determine if a .dll or anyother file for that matter is in use
and the contents can not be written to?
You don't, short of opening the file for exclusive access and seeing if it
fails. If you want to dig into the guts of the OS, there are low-level ways
to determine if a file is in use, but I don't know if you are ready for that
yet.
Quote
The scheme I have come up with my exe for being updated is to have
a separate an overwrite.exe program the main.exe creates a new
process calling the overwrite.exe if main.new exists. Then main.exe
closes. Overwrite waits until main.exe is closed and then writes the new
main.exe and then starts main.exe up again.
There is nothing wrong with that scheme, it is very common to use.
Quote
I suppose I could use the scheme for my dll updating but problem is
more than app could be using the .dll
If more than one app are using the DLL, then you're going to have a
difficult time updating the DLL.
If all of the apps are created by you, then one thing you could try is use
RegisterWindowMessage() to register two unique messages, and then write all
of the programs to catch those messages. Use SendMessage(HWND_BROADCAST,
...) to send the messages to all active windows in the system, and only your
own programs will recognize and react to the messages. Then you can send
one message when you are getting ready to update the DLL, so that each
program can release their handles to it first. Then after the update, send
the other message to let the programs know that they can load the DLL again.
Otherwise, you may have no choice but to simply use MoveFileEx() to delay
the update until the next reboot.
Gambit
 

Re:DLL and Forms

Ohh also when I use Dynamic RTL is checked and Build with Runtime Packages
is Checked for my project settings, by default what is the search order for
linking in the dll's? For example does it check the root directory first,
then check the system directory, and then the system32 directory?
 

Re:DLL and Forms

"JunkMail" < XXXX@XXXXX.COM >wrote in message
Quote
Ohh also when I use Dynamic RTL is checked and Build with Runtime
Packages is Checked for my project settings, by default what is the search
order for linking in the dll's?
The same as with loading any libraries in general. Look at the
documentation for LoadLibrary(), it explains the search order. Essentially:
When no path is specified, the function searches for the file in the
following sequence:
1. The directory from which the application loaded.
2. The current directory.
3. Windows 95: The Windows system directory. Use the GetSystemDirectory
function to get the path of this directory.
Windows NT: The 32-bit Windows system directory. Use the
GetSystemDirectory function to get the path of this directory. The name of
this directory is SYSTEM32.
4. Windows NT: The 16-bit Windows system directory. There is no Win32
function that obtains the path of this directory, but it is searched. The
name of this directory is SYSTEM.
5. The Windows directory. Use the GetWindowsDirectory function to get
the path of this directory.
6. The directories that are listed in the PATH environment variable.
The first directory searched is the one directory containing the image
file used to create the calling process (for more information, see the
CreateProcess function). Doing this allows private dynamic-link library
(DLL) files associated with a process to be found without adding the
process's installed directory to the PATH environment variable.
Gambit
 

Re:DLL and Forms

"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote

"JunkMail" < XXXX@XXXXX.COM >wrote in message
news:3fbec1c3$ XXXX@XXXXX.COM ...

>Can I simply use the dllimport as I was in the previous code and
>then in my project options under advanced linker Dlls to delay-load
>just put my DLL's in there?

The delay-load mechanism uses the Load/FreeLibrary() and GetProcAddress()
functions internally.

So I can use the delay-load mechanism and use the dllimports as before? If
I don't use the dllImports How do I call the function in the dll?
Quote
You don't, short of opening the file for exclusive access and seeing if it
fails. If you want to dig into the guts of the OS, there are low-level
ways
to determine if a file is in use, but I don't know if you are ready for
that
yet.
:) Ohh I'm ready Nah easier just useing a try catch :)
Thanks for info on MoveFileEx
I guess I'll try using the same scheme as before and the files I can't write
I use the MoveFileEx and make the end user reboot if it couldn't write any
of those files.
 

Re:DLL and Forms

"JunkMail" < XXXX@XXXXX.COM >wrote in message
Quote

"Remy Lebeau (TeamB)" < XXXX@XXXXX.COM >wrote in
message
news:3fbec687$ XXXX@XXXXX.COM ...
>
>"JunkMail" < XXXX@XXXXX.COM >wrote in message
>news:3fbec1c3$ XXXX@XXXXX.COM ...
>
>>Can I simply use the dllimport as I was in the previous code and
>>then in my project options under advanced linker Dlls to delay-load
>>just put my DLL's in there?
>
>The delay-load mechanism uses the Load/FreeLibrary() and
GetProcAddress()
>functions internally.
>

I tried putting DLL1.dll in the delay-load dll and using the dllimport
method as before. I still get that unresolved external linking error. So I
guess I can't use that. If the delay-load mechanism uses the
Load/FreeLibrary and GetProcAddress funtions internally, does it create long
pointers to my functions in the dll? Whats the naming convention for using
the functions?
I was reading into the delay-load in the help files. It seems that it won't
actually load the dll until it reaches a point in the executable that needs
it to be loaded. Does it unload it when the program terminates or does it
unload it just when it wants to?
Also the __FUnloadDelayLoadedDLL funtion returns true if succeeds false if
an error occured. If my executable never gets to a point where it needs to
load in the dll and I call the __FUnloadDelayLoadedDLL function will it
return true or false?
If I used delay-loading and call __FUnloadDelayLoadedDLL and then write out
my new.dll file do I need to call LoadLibrary right after I save it or will
the program load it again when it is needed?
Thanks for all your help Gambit. Much appreciated.
 

Re:DLL and Forms

Quote
I tried putting DLL1.dll in the delay-load dll and using the dllimport
method as before. I still get that unresolved external linking error.
Actuall I'm also getting the [Linker Error] Delayed load module DLL1.DLL was
not found. I simply clicked on the ... selected DLL1.DLL which is in the
current directory as my .exe and hit the add button. I'm still getting
unresovled externals but that could be due to the fact that its not finding
the dll1.dll to delay load.
I'm missing something in the project settings for using delayed loading?
 

Re:DLL and Forms

"JunkMail" < XXXX@XXXXX.COM >wrote in message
Quote
So I can use the delay-load mechanism and use the dllimports as before?
I think that is a round-about way to make use of the delay-load mechanism.
However, I just did a test and was able to unload and replace a delay-loaded
DLL at runtime without any problem when using dllimport, so it is
technically possible.
Quote
If I don't use the dllImports How do I call the function in the dll?
I already showed you a code example earlier of exactly that.
Quote
I guess I'll try using the same scheme as before and the files I can't
write I use the MoveFileEx and make the end user reboot if it couldn't
write any of those files.
Also, please read the documentation for MoveFileEx(). It only works for
WinNT/2K/XP. For Win9x/Me, you have to use the WININIT.INI file instead.
The documentation for MoveFileEx() explains the requirements for it, though.
Gambit
 

Re:DLL and Forms

"JunkMail" < XXXX@XXXXX.COM >wrote in message
Quote
I tried putting DLL1.dll in the delay-load dll and using the
dllimport method as before. I still get that unresolved external
linking error. So I guess I can't use that.
Yes, you can. If you are still getting the same errors, then your files are
still not set up correctly to begin with. Please show your updated code.
Quote
If the delay-load mechanism uses the Load/FreeLibrary and
GetProcAddress funtions internally, does it create long pointers to
my functions in the dll?
When you call a function in a delay-loaded mechanism, the RTL is essentially
doing the same thing that I showed you in my example code earlier. However,
it also places the loaded DLL's HINSTANCE and the retreived function pointer
from GetProcAddress() into a global list of pointers so that as you continue
to call into the DLL during the lifetime of the program, it only has to load
the pointers once.
Whenever you call a function of the DLL, if you are not using the delay-load
mechanism, the compiler can emit machine code that calls the function
directly, since the DLL is always loaded in memory at all times before any
of your application's code is ever executed. However, using the delay-load
mechanism, the DLL is not loaded right away, and the compiler has to emit
extra machine code that looks in the global list to see if a pointer to the
requested function is available or not. If not, then the pointer is loaded
and stored for later use. Then the compiler's machine code can call the
function via the retrieved pointer. Yes, that does invoke a little bit of
extra overhead on every call to a delay-loaded function, since it has to do
a runtime lookup every time to see if the function is availabe for calling,
but the overhead should be minimal.
Quote
Whats the naming convention for using the functions?
The naming convention uses the same rules whether the DLL is delay-loaded or
not. Delay-loading does not effect the actual DLL in any way, only in how
it is accessed. The naming is controlled by the actual calling conventions
(__cdecl, __stdcall, etc.) that are applied to the actual functions which
are being exported, as well as the presence or lack of name mangling. The
.LIB file for the DLL contains the exported names, so the compiler always
knows what the names are, whatever they happen to be. If you were writing
the loading code manually by calling Load/FreeLibrary() and GetProcAddress()
yourself, you would have to look up the actual exported names yourself.
Quote
I was reading into the delay-load in the help files. It seems that it
won't actually load the dll until it reaches a point in the executable
that needs it to be loaded.
Correct. Thus the name "delay" loading :-)
Quote
Does it unload it when the program terminates or does it unload
it just when it wants to?
Once loaded, the DLL remains loaded for the lifetime of the program and is
then unloaded during the program's cleanup operations.
Quote
Also the __FUnloadDelayLoadedDLL funtion returns true if succeeds
false if an error occured. If my executable never gets to a point where
it needs to load in the dll and I call the __FUnloadDelayLoadedDLL
function will it return true or false?
That depends on whether you are calling it with an actual filename to unload
a single DLL, or if you are specifying NULL to unload all DLLs. If a
filename is specified, then it rill return FALSE if the DLL was not loaded.
If NULL, it will always return TRUE regardless of error.
Quote
If I used delay-loading and call __FUnloadDelayLoadedDLL and then
write out my new.dll file do I need to call LoadLibrary right after I save
it or will the program load it again when it is needed?
It will be re-loaded when actually needed.
Gambit