Solved

Smart DLL loading

Posted on 1998-10-05
36
685 Views
Last Modified: 2013-12-14
Hello,

Microsoft Visual C++ 5.0
also Borland C++ Builder 3

I would like to load DLL dynamically but still use classes exported from that DLL.
(something between statically and dynamically loading DLL)
I would like a lib that would allow use of exported stuff but won't automatically load
DLL.
I would load it later IF I have it and if not I would set flag so I won't use any of
unaccessable stuff.
Another use of this: I have plug-in modules I would like to comunicate with through
classes - so I won't know actual DLL name at compile time. Also DLL name could
change at compile time.

Example:
    /** DLL **/
    __declspec(dllexport) class ThisIsIt
    {
     public:
        int i;
        virtual int DoSomething();
        int MainFunction(int data);
    };
    // ...

    /** EXE **/
    class UseThisIsIt : public ThisIsIt
    {
     public:
        int DoSomething();
    };
    // ...
    int UseDLL()
    {
        if (isDllLoaded)
        {
            UseThisIsIt useThisIsIt();
            //...
            return useThisIsIt.MainFunction(data);
        }
        else
            return -1; // Error indicator
    }

Once again: I would like to load this DLL dynamically and use it this way.

Thank you,
    Janez

--
Regards,
 Janez Resnik
 ib-CADdy d.o.o.
 Ljubljana, Slovenia
 mailto://janez.resnik@ib-caddy.si
0
Comment
Question by:jr001
  • 15
  • 8
  • 6
  • +3
36 Comments
 
LVL 8

Expert Comment

by:Answers2000
ID: 1174370
1. In DLL's .h (say DLL.H)

#ifdef BUILDINGDLL
#define DLLCLASS __declspec(dllexport)
#else
#define DLLCLASS __declspec(dllimport)
#endif

2. In DLL's .cpp (say DLL.CPP)
#define BUILDINGDLL
#include "dll.h"


3. In EXE
#include "dll.h"

You UseThisIsIt class should use LoadLibrary to load the DLL (and FreeLibrary later to release it)

If the the Library is loaded then you can simply use new to create objects of the DLL classes

class UseThis : public CObject
{
private:
 HINSTANCE m_hInst ;
 ThisIsIt * m_pThisIsIt ;

public:
  UseThis()
  { m_hInst = NULL ; }

  virtual ~UseThis()
  {
    if ( m_hInst != NULL )  FreeLibrary( m_hInst ; ) ;
  }

  BOOL LoadLibrary() // return TRUE if DLL loaded okay
  {
    m_hInst = LoadLibrary( "MYDLL.DLL" ) ;
    return ( m_hInst != NULL ) ;
  }

  BOOL IsDLLLoaded() const // return TRUE if DLL is loaded
  {
    return ( m_hInst != NULL ) ;
  }

  int UseThisIsIt()
  {
    // see below
  }
 
} ;


The best way to write UseThisIsIt is :-
i. Add to DLL an exported function (outside any class) to new ThisIsIt object's and return a pointer to this.

ii. In UseThisIsIt, check value of m_hInst.  If not NULL use GetProcAddress to get pointer to the function number i.

iii. Use function ptr return from GetProcAddress (will have to cast the return value into a function pointer of the correct type) to call function i.

iv. You now have a ptr to ThisIsIt object, add through that can call any members of the objects

v. Don't forget to delete the ThisIsIt object when you're done with it.  A good way to keep track may be to remember that pointer in UseThisIsIt class as a member variable, and delete it in the destructor before calling FreeLibrary

0
 
LVL 22

Expert Comment

by:nietod
ID: 1174371
In this sort of design a class hierarchy often makes the most sense.  There is an include file that defines a base class that both the EXE and the DLL "see", but the DLL (or DLLs) define derived classes that the EXE doesn't know about.  But the EXE can get pointers to objects of these derived classes from the DLLs it loads.
0
 
LVL 4

Author Comment

by:jr001
ID: 1174372
This is the way. But this is not what I am asking for. (I knew THIS way is possible)

When I compile DLL, I get .lib file, which I include in EXE file and this EXE file can call and  use anything exported from DLL. It also loads DLL when EXE is starting. This is what I would like to avoid or edit.

Let's go to low level. In EXE which is using DLL, some code is automatically inserted that can call exported stuff in DLL. This is transparent to the programmer.

Is there any way to get behind the curtain, begind the stage - to modify what is automatically done (to skip (or modify) automatic load and do it later manual).

What is wrong with your solution? I cannot have any variable in root class (the one in dll) - I must have method to access it. (I created properties for this case, but this is another story).

I say this question is linker - specific.

Thank you,
   Janez
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174373
The problem is that your are linking the DLL's .lib file to the EXE.  That will force the EXE to load the DLL at startup.  Do not link and you will be fine. To do this in MSVC++, just indicate that the EXE project does not depend on the DLL project.  (somewhere there is a  "dependancies" dialog).
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174374
However, if you do that, then
A.  Your EXE cannot be compiled with external declarations for the DLL's procedures and classes, i.e. you cannot include .h files from the DLL into the EXE.
B.  Your EXE cannot call procedures defined in the DLL in the typical straightforward way.  Instead you must use GetProcAddress() to get a pointer to the procedure to be called, then call through the pointer.
C.  You must explicitly load the DLL with LoadLibrary() and release it with FreeLibrary().
0
 
LVL 86

Expert Comment

by:jkr
ID: 1174375
See 'http://www.codeguru.com', section 'Win32', article 'Dynamically loading Classes from DLLs'
0
 
LVL 4

Author Comment

by:jr001
ID: 1174376
I am not happy with an answer. I must admit the solution pointed by jkr is quite good, but it is still the same story.

Is there really no way to abort or change automatic DLL load. Someone who knows everything about Win32 EXE file layout - maybe I could change EXE after compilation and then load DLL as needed.

Does anybody know what is that lib (we get when building DLL) composed of (deepest details)? My idea is if I could change this lib I could achieve what I want to.

I would really like to do this the most transparent way possible.

Thank you,
    Janez

PS: Is there any way to split points? I would give them to more people. No answer is worth whole 100 pts. to me, but all together are almost that good.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174377
>>Does anybody know what is that lib (we get when building DLL)
>> composed of (deepest details)? My idea is if I could change this
>> lib I could achieve what I want to.
Like any other library, it is just compiled code.  When you crompile a regular code library into a .lib file, you get the code for each of the library's procedures in the .lib file   However, in the case of a DLL, the code is not the complete code for the DLL's procedures.  Instead the code consists of jump instructions that jump to each of the procedures in the DLL.  That is, each exported procedure int he dLL produces a jump instruction in the .lib file.

In addition to that, the .lib file contains information used at EXE startup to perform the dynamic link.  The information is the expected base address of the DLL and the filename of the DLL.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174378
>> Is there really no way to abort or change automatic DLL load.
>> Someone who knows everything about Win32 EXE file layout -
>> maybe I could change EXE after compilation and then load DLL
>>  as needed.
Why?  What does this accomplish for you that you can't accomplish more safely using traditional techniques.

You could change the EXE, but that is dangerious and impossible to do from within the EXE (it is too late byt he time it is running, and the files is open read-only anyways)  You can change the EXE file from another EXE and then run it.  That would work--don't do it anyways.

A technique I used is to change the name of the DLL.  You may have 2 or 3 DLLs that have the same exports.  You rename one of them to the name that is used by the EXE (prior to running the EXE.)
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174379
If this isn't of any help.  Can you explain what you ultimate goal is and why the traditional LoadLibrary() aproach isn't good enough.
0
 
LVL 86

Expert Comment

by:jkr
ID: 1174380
Well, using the way i suggested, you don't have to care about import libraries...
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174381
Same with the ways that answers2000 and I proposed.
0
 
LVL 8

Expert Comment

by:Answers2000
ID: 1174382
Ditto, the original rejected answer I gave doesn't need the .LIBs
0
 
LVL 86

Expert Comment

by:jkr
ID: 1174383
nietod - sure! I think we'll have to convince jr001 that he doesn't need a .lib ...
0
 
LVL 86

Expert Comment

by:jkr
ID: 1174384
nietod - sure! I think we'll have to convince jr001 that he doesn't need a .lib ...
0
 
LVL 4

Author Comment

by:jr001
ID: 1174385
I will have to try this out in my example.

(to nietod:) I cannot rename DLL before start. Actually I am not even sure if there is any and what is its name. I will have to read DLLs name from registry.

I want to be able to use several DLLs with same interface, connecting one at the time in some loop. Another problem: if DLL is present, use it, otherwise some commands in menu should be disabled.

After all - you are probably right, I expect too much. I just wanted to find the simpliest way to use DLL same as before but to load it dynamically now. And I really hate using GetProcAddress - compiler cannot check for misuse of parameters. I am a few steps closer to my goal after this conversation.

I will be checking this out as soon as I find some time.

Thank you,
   Janez
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174386
>> I really hate using GetProcAddress - compiler
>> cannot check for misuse of parameters. I am a few steps closer to
>> my goal after this conversation.

You can make it nearly 100% save using a class hierarchy, as I suggested before.  define a base class that the EXE and DLLs all know about.  Define virtual functions for each of the procedures you want to call from the DLLs.  Then let the DLLs define derived classes that have different versions of these procedures.  Each DLL will have a procedure that takes no parameters but returns a pointer to an object from this class heiarchy.  The EXE has to call only one procedure using GetProcAddress() and this procedure takes no paramaters.   Pretty safe.  After than, the EXE uses the object pointer that was returned by the procedure to make all other calls.  C++ can check these.  I use this and can verify that it is a safe and effective solution.
0
 
LVL 86

Expert Comment

by:jkr
ID: 1174387
OK - nietod is absolutely right. The only way to make it handier would be COM... and that's quite similar to using a interface with virtual functions...
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 4

Author Comment

by:jr001
ID: 1174388
I was considering COM or ActiveX could be a solution, but as I guess this is slower way to do my job.
Does anybody have any experience concerning speed. I am sure loading of COM is slower than for ordinary DLL; what about runing program (calling methods, accessing properties)?
I want to know everything. This is long term decision I have to make.

Thank you,
   Janez
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174389
COM and ActiveX may take longer to load and set up, but they should run as fast as any other mechanism.  The calls you make are through a jump table, just like a C+++ virtual function call.  That is a very fast technique for "selecting" the right funciton to call.
0
 
LVL 86

Expert Comment

by:jkr
ID: 1174390
Well, i had to make a decision like this at the beginning of the year, and COM had proven to be the best choice - it meets all your requirements.
0
 

Expert Comment

by:dousuck2
ID: 1174391
As soon as this thing is unlocked i'll tell ya a way to load a dll at runtime and never have to use any export/import complier directives.
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174392
>>load a dll at runtime and never have to use any
>> export/import complier directives
That's not what the question is about.  Besides you obviously don't need export/import directives to load a DLL at run-time.

The question is how to
>> load DLL dynamically but still use classes exported from that DLL.

0
 

Expert Comment

by:dousuck2
ID: 1174393
I might have stated my comment wrong, but the right answer is not to export classes.  Exporting entire classes from a dll is a nightmare.  It might be ok for a 5 or 6 small classes, but not for anything much bigger.  I've read tales of how the MFC team deals with the MFC dll and it's not pretty, but they do essentally what your asking for.  I recommend using a single 'CreateObject' like call exported by a def file that returns pure virtual interfaces.  Like COM, but not COM. You control the load time and minor changes to the dll such as adding a data member or function does not effect your exported symbols.  I've done it, it works.  But what do i know...
0
 

Expert Comment

by:dousuck2
ID: 1174394
I might have stated my comment wrong, but the right answer is not to export classes.  Exporting entire classes from a dll is a nightmare.  It might be ok for a 5 or 6 small classes, but not for anything much bigger.  I've read tales of how the MFC team deals with the MFC dll and it's not pretty, but they do essentally what your asking for.  I recommend using a single 'CreateObject' like call exported by a def file that returns pure virtual interfaces.  Like COM, but not COM. You control the load time and minor changes to the dll such as adding a data member or function does not effect your exported symbols.  I've done it, it works.  But what do i know...
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174395
Have you read the question history?  That was already suggested.
0
 
LVL 4

Author Comment

by:jr001
ID: 1174396
I WANT to see if dousuck2 has better answer. That's the only reason I am rejecting answer now.

Thank you for understanding.
0
 
LVL 2

Expert Comment

by:mnguyen021997
ID: 1174397
w/o com there's no automatic way.  the best you can do is write a wrapper class that essentially does a getprocaddress based on the dll that is loaded. so just using c++, you would write:

class myclass
{
  private:
    func1 lpProc1;
    func2 lpProc2;

  public:
    myclass( const char* szDll )
    {
        HINSTANCE dll = loadlibrary(szDll);
        lpProc1 = (func1) getprocaddress( "func1" );
        lpProc2 = (func2) getprocaddress( "func2" );
    }

    void func1() { (*func1)(); )
    void func2() { (*func2)(); }
};

*** error handling intentially ommitted
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174398
What is happening with this question?
0
 
LVL 4

Author Comment

by:jr001
ID: 1174399
(to mnguyen)
Nothing new. Sorry.

(to nietod)

nothing. apparently...

I invite >>nietod<< to answer this question again so I can grade him and close up. He gave me the most of new information, since I never got the answer I asked for or wanted.
0
 
LVL 22

Accepted Solution

by:
nietod earned 100 total points
ID: 1174400
What is it that you are still looking for?  You should be able to use LoadLibrary() for your purposes.  If the EXE defines an abstract base class and the DLL loaded defines a derived class or classes (which one or two procedures found with GetProcAddress()  returns pointers to)  You can easily use the library in this way.
0
 
LVL 4

Author Comment

by:jr001
ID: 1174401
I don't know if I am able to explain this. It seems nobody understand (or doesn't want to).

*****
I wanted to fool around linker to believe dll is stactically linked, and on other hand don't load dll on start.
*****

My original idea was to use .lib file and enable it to load (any-named) dll later any number of times
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174402
>>I wanted to fool around linker to believe dll is stactically linked, and on
>>other hand don't load dll on start.

The loading of the DLL has nothing to do with the linker.  That happens when the program is run.  You can't change that.  But you don't need to either.  (If you corrupted the file so that the OS didn't try to load the DLL, then it wouldn't be able to do its fix-ups so you wouldn't be able to use the DLL as it were statially linked anyways, so there is no hope in this approach).

Forget how you want to get it done.  Just explain what your needs are.  
0
 

Expert Comment

by:dousuck2
ID: 1174403
I understand what he wants, it's a variation of what the MFC team does.  Yet, i haven't been able to find where i found this info.  I don't think it explained how they did it anyways.  If i remember correctly, they basicly replace some of the exported calls with stub functions that load the needed system dlls when called and then do the fixup again.  It's something like that... It's really a complicated mess.  I wish i had more on this for ya.
0
 
LVL 4

Author Comment

by:jr001
ID: 1174404
I noticed MFC42.DLL (also some others) is loaded after InitInstance is called. This gave me idea to do this same thing myself. (You know that for user MFC42.DLL appears like statically linked)
0
 
LVL 22

Expert Comment

by:nietod
ID: 1174405
Well it sounds like what dousuck2 is talking about.  You gave up a little too soon.  If he can help you, I'll ask a dummy question for him to give the points.

However, I don't think think you really need this sort of approach.  With C++'s virtual functions you can get all the benefits of static linking from a dynamically linked DLL.  You will need to use GetProcAddress() only one time to get a procedure to call that returns an object to you.  After that you do not have to use GetProcAddress and procedure pointers again.  Just normal C++ code.  
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now