Re: Allow DLLs to access a Singleton
Ben Pope wrote:
<fernando.a.gomez.f@gmail.com> wrote in message
news:1152571362.177971.51220@35g2000cwc.googlegroups.com...
Ben Pope wrote:
Hi,
Currently I have a main application that loads DLLs. The main
application
has a factory, that is a singleton. How do I allow the DLLs to access
that
singleton?
I have made the singleton pretty basic for brevity, and MyClass is not
much
of a factory, but it illustrates the problem.
Currently I have something like:
Test.hpp:
----
#include <iostream>
class MyClass {
int val_;
public:
MyClass() : val_(0) {
std::cout << "MyClass()" << std::endl;
}
void value(int val) { val_ = val; }
int value() { return val_; }
};
template<class T>
class Singleton {
private:
static T* t_;
Singleton();
public:
static T& Instance() {
if (!t_) {
t_ = new T;
}
return *t_;
}
};
typedef Singleton<MyClass> MySingleton;
Test.cpp
----
#include "test.hpp"
template<class T>
T* Singleton<T>::t_ = 0;
TestDll.cpp
----
#include "..\test\test.hpp"
//#include <windows.h>
_declspec(dllexport) void Register(MySingleton& mine) {
mine.Instance().value(9);
}
Main.cpp
----
#include "test.cpp"
#include <iostream>
#include <windows.h>
int main() {
MyClass& mine = MySingleton::Instance();
std::cout << mine.value();
mine.value(5);
std::cout << mine.value();
typedef void(*FunctionRegister)(MySingleton&);
HMODULE mod = LoadLibrary("TestDll.dll");
if (!mod) {
std::cout << "Libray Failed to Load" << std::endl;
return 1;
}
FunctionRegister reg = (FunctionRegister)GetProcAddress(mod,
"Register");
if (!reg) {
std::cout << "Failed to Find Function \"Register\"" << std::endl;
return 2;
}
reg(/* what goes here? */);
}
Since MyClass is never instantiated, I can't really pass them around. I
need for the DLL to know about the Singleton in the main application
without
creating it's own instance, completely defeating the point. At the
moment,
the static MyClass* is an unresolved external for the DLL.
Thanks for any pointers (pun not intended)!
Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Hi Ben,
since MySingleton::Instance() returns the same always, why do you need
to pass a MySingleton instance as a parameter? I mean, I think that is
against the singleton pattern. I'd just do something like:
_declspec(dllexport) void Register()
{
//mine.Instance().value(9);
MySingleton::Instance().value(9);
}
Then in your main function I'd put something like:
// ...
FunctionRegister reg = (FunctionRegister)GetProcAddress(mod,
"Register");
if (!reg) {
std::cout << "Failed to Find Function \"Register\"" << std::endl;
return 2;
}
reg();
// ...
OK, I understand what you're saying, it was actually my first attempt. The
problem is how do I get the static MyClass* to not be an unresolved
external?
If I put the test.cpp bit into the header, then my main application and the
DLL will each have their own singleton... I need some way of dealing with
that, and I'm not sure what that is.
I'm a bit of a DLL newbie, although I'm quite comfortable with C++.
Cheers,
Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Hi Ben,
you'll be needing neither a MyClass pointer nor a reference because
this is encapsulated by the Register function. However, if you're
planning to use MyClass elsewhere outside the DLL, you'll need to
export MyClass as well by adding the __declspec(dllexport) modificator
-just as you did with Register function. However, for loading it,
you'll need to declare the class again now with the
__declspec(dllimport) modifier. Then you'll have to reference the DLL
in the project settings (reference the .lib file that is generated in
the C++ options).
Finally, note that usually you'll do something like:
#ifdef MYAPP_EXPORTS
#define MYAPP __declspec(dllexport)
#else
#define MYAPP __declspec(dllimport)
#endif
....
class MYAPP MyClass { ... };
so that you can use the same header file from both the DLL project and
the client project (The DLL project called MyApp usually #defines the
symbol MYAPP_EXPORTS.
Regards,
FG.