2

I'm writing a DLL in C++ for use with VB6. As such, I cannot have a constructor called in my DLL (according to this discussion). However, I need to maintain an instance of a class internally -- so I intend to keep the object as a global variable and call the constructor from a global function, and after that, use another global function to call a method on the object.

I had the idea that maybe one function would be enough: It would check if an instance is present in a global variable, and if not, create it, and then call the method on the object (or, if it is present, immediately call the method.)

Now, how can I find out whether an instance is already created? I can't assign a global variable any value in the declaration, right? And they also don't have a guaranteed default value in C++, as far as I understand.

Therefore my question: Is this possible anyway and how?

Or can I use the BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) function to initialize variables? If so, can someone fill me in on what the ul_reason_for_call cases exactly are and which of these is automatically called when VB6 loads the DLL as in my linked example?

Community
  • 1
  • 1
Felix Dombek
  • 13,664
  • 17
  • 79
  • 131
  • I wouldn't do it in the DllMain. But why don't you use a helper class that wraps a static member of your class, and all your global functions (that are called by VB6) can work off that instance? – Sasha Goldshtein Feb 01 '11 at 13:17
  • @Sasha: But doesn't that still imply that I need to create some instance before I can access its methods? Please be a little more specific, I don't quite understand! – Felix Dombek Feb 01 '11 at 13:21
  • Your boss wants you to write a COM server. You need to learn ATL. – Hans Passant Feb 01 '11 at 15:07
  • @Hans: This is a rather simple project and I think using COM would be overkill. Putting the DLL in the system folder and doing `Declare Function foo Lib "bar.dll"` should be totally sufficient for the purpose of this project. But if it should turn out to be inevitable that I use COM, I'll do so later ... which will probably result in an awful lot of questions on SO ... – Felix Dombek Feb 01 '11 at 15:23

3 Answers3

2

Suppose you want an instance of MyClass to be acessible globally. You can have a class with a static member which your global functions will access:

class GlobalHelper {
public:
   static MyClass* GetInstance() {
      static MyClass inst;
      return &inst;
   }
};

...and then your global methods would be calling GlobalHelper::GetInstance()->Whatever() to do their work.

Sasha Goldshtein
  • 3,499
  • 22
  • 35
  • Oh, thanks, interesting, I haven't used static variables in C++ until now. So that makes sure that the instance `inst` is created only once when `GetInstance()` is called for the first time, and then reused at every further call? And does it also work with parameters to pass to the constructor? What would happen if the parameters change? Is then a new instance created, but if they stay the same over two calls, the old one is reused? – Felix Dombek Feb 01 '11 at 13:30
  • It won't work if you need different parameters every time. But you can extend this idea further by storing the objects in a `std::map` indexed by the parameter tuple. – Sasha Goldshtein Feb 01 '11 at 13:46
2

You can use global static variables or file scope variables in your CPP files:

bool bInited = false;
MyClass* pClass = NULL;

These assignment statements will be called inside DllMain, later you can test if they have been initialized properly.

You could declare the pointers as auto_ptr (if you use stl or something equivalent), to have the destructors called on exit.

1

You don't even need a function:

class MyThingy
{
} my_global_thingy;

my_global_thingy will be instantiated at program startup, before DllMain is executed.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • Oh, I hadn't thought about that! Also very interesting. I guess the default constructor is used? Can I also have a different one called? – Felix Dombek Feb 01 '11 at 13:32
  • @Felix: Yes, the default ctor is called. No, you can't call another one the way I've written it. – John Dibling Feb 01 '11 at 13:42
  • Before DllMain is executed? I think you are confused with the C/C++ main() function. When your DLL/EXE loads, the OS invokes DllMain/WinMain before anyting else. –  Feb 01 '11 at 16:01