DLL Problem....

Started by
11 comments, last by Evil Steve 19 years, 1 month ago
I have a dll problem. I have developed a plugin system that loads dlls from a certain folder. I have an interface layer which has certain function the dll can call, but this gets passed in when I call init in the dll. I have a main application that I don't want the dlls to interact with, thats the reason for the interface layer. But the interface layer references the main application in it. So what happens is that I create the main application and then the dll is creating a second main application because it is referenced in the interface layer. The main application and application interface are both singletons. What I would like to do is have the dll not create a second main application and use the current one that was created already and is referenced in the application interface that is passed to the dll. Sorry if so confusing. Just ask any questions if you don't understand. Thanks in advance. -Jay
Its not a bug, its a feature!!
Advertisement
I have a habbit of putting stuff in DLLs all the time. What I *always* do is have to abstract classes. One which the DLL implements, and one which the EXE implements, and passes to the DLL.

For example, my bomberman clone has the AI in a DLL. The AI interface has functions like OnTick() and OnNewMap(), and the EXE interface has functions like GetPlayerPos(), MoveLeft(), DropBomb(), etc etc.

My main application class derives from this virtual class, and provides functionality for the functions (GetPlayerPos(), MoveLeft(), DropBomb(), etc).
When I load the DLL, I use GetProcAddress() to get the address of the Create() function. I then call it, passing this to it, as the abstract class.

That's a really bad explanation [smile]. I export the function from the DLL as:
extern "C" {AI_API IAI* CreateAI(IGameInterface* pInterface);}


In your case, if you really want to use a singleton, you'd just pass the singleton through as the interface. For example m_pAP = pfnCreate(&CGame::Get());.

Hope this helps,
Steve
This is pretty much what I do, I pass the application interface instance to the dll, but when the main application is referenced in the application interface via MainApplication::GetInstance()->SomeFunc(), it creates a second main application instance, so is there a way for it not to create a second when it tries to access the main application.

-Jay
Its not a bug, its a feature!!
I'm not entirely sure I understand...

If you pass a pointer to the singleton to the DLL, then the DLL shouldn't care if the passes pointer is a singleton or not. So it shouldn't need to call the Get() method, which would cause another instance to be created.

Example code:
//// Your interfaces//class IDll{public:   IDll() {}   virtual ~IDll() {}   virtual void Release() = 0;   virtual void Tick() = 0;};class IGameInterface{public:   IGameInterface() {}   virtual ~IGameInterface() {}   virtual HWND GetWindow() = 0;   virtual void DoSomething() = 0;};// Exported function:IDll* CreatePlugin(IGameInterface* pInterface);//// In the DLL://class CDll : public IDll{public:   CDll(IGameInterface* pInterface) : m_pInterface(pInterface) {}   virtual ~CDll() {}   virtual void Release() {delete this;}   virtual void Tick() {m_pInterface->DoSomething();}protected:   IGameInterface* m_pInterface;};// Exported function implementation:IDll* CreatePlugin(IGameInterface* pInterface){   return new CDll(pInterface);}//// In the exe://class CGame : public IGameInterface{public:   CGame() {}   virtual ~CGame() {}   virtual HWND GetWindow() {return m_hWnd;}   virtual void DoSomething() {/* Blah */}   static CGame& Get()   {      static CGame theInstance;      return theInstance;   }protected:   HWND  m_hWnd;   IDll* m_pPlugin;   // Etc};//// When you load the plugin:// - Assume pfnCreate is the CreatePlugin() function from GetProcAddress()//m_pPlugin = pfnCreate(&CGame::Get());

This way, the DLL doesn't care that the game class is a singleton - in fact it has no way to refer to it as such, so there'll only be one copy created in the EXE.
I have two singletons MainApplication and ApplicationInterface.
ApplicationInterface uses MainApplication. I pass the ApplicationInterface singleton pointer, but because that references MainApplication. That creates a second MainApplication pointer from within the ApplicationInterface, when one was created earlier before from the main game.

Hope that helps.

-Jay
Its not a bug, its a feature!!
Ohhh, I see (Sorry, I'm slow [smile]).
I think that your best bet is to combine MainApplication and ApplicationInterface into one class. I can't really see any reason for seperating them.
Alternatively, you could have a pointer to MainApplication inside ApplicationInterface that you could set at startup, and use that instead of MainApplication::Get(). It's pretty ugly, but that's all I can think of.
Ok, I think I fixed it, if something else goes wrong then I'll post.

Thanks, Evil Steve, for pointing me in the right direction.

-Jay
Its not a bug, its a feature!!
It is my understanding of dlls is that dlls copy their data for the different proccesses. Is that correct? If so is there a way to make the dll use existing data and not let it make a copy of data? Example: If I make a class outide the dll and then want to use that class in the dll, it creates a second one, I don't want it to do this, I want it to use the one I created first. Is there a way to do this?

-Jay
Its not a bug, its a feature!!
As far as I know, you can only do this if the one instance of the data is in the DLL. You can declare a section of the DLL shared, and put the variable in there.
All prigrams that link to the DLL access the same variable, instead of getting their own copies of it.
Here's the source from a keyboard hooking program I wrote a while ago (The pragmas are for MSVC 6.0, but they'll probably work in VC 2003 or 2005):
// Declare these as system-wide globals (shared) //#pragma data_seg(".Dll")HHOOK g_hHook = NULL;#pragma data_seg()#pragma comment(linker, "/section:.Dll,rws")

That means that all exe's that link to the DLL access the same g_hHook varible. Without this, if two exe's load the DLL, they'll each get their own instance of the variable. So if program 1 sets it, it'll still be NULL in program 2. If the segment is shared, then when program 1 changes the variable, program 2 will see the change.
Ok now based on this is there any way to flip this, and have the program make the classes and the dll just uses them without creating its own? Example I have a class called EventSystem that has a static map member and a static function called SendMessage, now EventSystem is the base class for each System, and it adds itself to the static map member and if it needs to send a message to another system it uses SendMessage which looks into the map for the System it wants to send to and if its there then it sends it. I have all this created already before the dll loads, but when I use SendMessage in the dll, it has created a second base EventSystem with no systems in it, when there should be some in there if it was the same system to begin with. So SendMEssage fails all the time because it can't find any systems in it.
Its not a bug, its a feature!!

This topic is closed to new replies.

Advertisement