Sign in to follow this  
Cluq

Static variable changes in dll

Recommended Posts

Cluq    122
Hi I have a problem. I have class A and class B, which are located in a dll. In WinMain (in my exe), I am setting A::myStaticVariable to some value. But when I from a method in class B check A::myStaticVariable it is null?! Does this make sense? Can the static variable be different from when it is in the exe, and when it is in the dll? I of course have checked (and rechecked) that A::myStaticVariable is not changed any where else.

Share this post


Link to post
Share on other sites
SiCrane    11839
It's possible in some cases for separate copies of a static variable to defined in different modules. For instance, this can happen with template classes. Check the address of the variable when accessed your executable and in your DLL to see if they are the same or not.

Share this post


Link to post
Share on other sites
Cluq    122
And I am exactly using templates in this case! (good ol' singletons)

Is there any way of fixing the problem? (except NOT to set static variables from a different module - I would still like to do this)

Thank you for the reply though!

Share this post


Link to post
Share on other sites
SiCrane    11839
In order to prevent different modules from creating their own copy of the static member variables, you should export the template from the DLL. This article shows the necessary syntax.

Share this post


Link to post
Share on other sites
Cluq    122
Many, many thanks! I have read (and reread) the article, but still can not get it working.

I have my singleton template class located in a dll:

template <class T> class __declspec(dllexport) Singleton {
static T* mySingleton;
}

And I have my class A, also in the dll:

class __declspec(dllexport) A: public Singleton<A> {}

Now, as I understand from the article, I should import the template instantiation into my exe by writing (in the exe):

extern template class __declspec(dllimport) Singleton<A>;

This compiles as it should, but my initial problem remains the same.

A check on A::mySingleton still yields a different result depending on whether it is done in the exe or in the dll.

Have I misunderstood something, or forgot something here?

Share this post


Link to post
Share on other sites
GamerSg    378
Hmm i use templates too for some of my code, but ive never run into such a problem. I believe your templated base class is all in the header? And this header is included in your exe as well?

I do it this way, (might not work for you, but might be worth a try)
Since my base class is all in the header, i do not export this.
template <class T>
class UniqueRegistry
{
....
}

For my derived classes, i export them in the DLL

class __declspec(dllexport) EffectRegistry : public UniqueRegistry<Effect>

In my exe,

the header is included with a minor change(obviously i use a typedef to automate this rather than making 2 header files)

class __declspec(dllimport) EffectRegistry : public UniqueRegistry<Effect>

And it appears to work with 1 copy of the instantiated object shared between DLL and exe. (Objects instantiated in DLL)

Share this post


Link to post
Share on other sites
SiCrane    11839
Example code of template class with static member variable shared between DLL and executable:

dll_header.h:

#ifndef TEMP_DLL_DLL_DLL_HEADER_H
#define TEMP_DLL_DLL_DLL_HEADER_H

#pragma warning(push)
#pragma warning(disable : 4231)

#ifdef COMPILING_TEMP_DLL_DLL
#define DECL_SPEC __declspec(dllexport)
#define EXP_TEMPLATE
#else
#define DECL_SPEC __declspec(dllimport)
#define EXP_TEMPLATE extern
#endif

template <typename T>
class DECL_SPEC ClassWithStatic {
public:
static T value;
};
template <typename T> T ClassWithStatic<T>::value;

EXP_TEMPLATE template class ClassWithStatic<int>;
EXP_TEMPLATE template class ClassWithStatic<float>;

DECL_SPEC void dll_function(void);

#pragma warning(pop)

#endif


main.cpp:

#include "../dll/dll_header.h"
#include <iostream>

int main(int, char **) {
ClassWithStatic<int>::value = 5;
std::cout << &ClassWithStatic<int>::value << ":" << ClassWithStatic<int>::value << std::endl;
dll_function();
std::cout << &ClassWithStatic<float>::value << ":" << ClassWithStatic<float>::value << std::endl;
}


dll_main.cpp:

#include "dll_header.h"
#include <iostream>

void dll_function(void) {
std::cout << &ClassWithStatic<int>::value << ":" << ClassWithStatic<int>::value << std::endl;
ClassWithStatic<float>::value = 0.25;
std::cout << &ClassWithStatic<float>::value << ":" << ClassWithStatic<float>::value << std::endl;
}

Share this post


Link to post
Share on other sites
Cluq    122
You are a GOD! :-)

I missed the fact that the difference (dllimport/dllexport and extern/no extern) had to be in the same header. I declared the exe part in the main header of my exe!

But now it works, and many, many thanks for the help!

Share this post


Link to post
Share on other sites
Cluq    122
But just to edge it into stone - a user of my dll would then be required to make a define when including the headers of my dll. If he doesn't, it wouldn't work, right?

Share this post


Link to post
Share on other sites
emeyex    382
No, they shouldn't have to do anything: notice in SiCrane's source code snippet:


#ifdef COMPILING_TEMP_DLL_DLL
#define DECL_SPEC __declspec(dllexport)
#define EXP_TEMPLATE
#else
#define DECL_SPEC __declspec(dllimport)
#define EXP_TEMPLATE extern
#endif



You need to define COMPILING_TEMP_DLL_DLL when you create your dll; when the client includes your header file, they should NOT have COMPILING_TEMP_DLL_DLL defined. This way, they'll automatically use the __declspec(dllimport) and extern declarations.

Share this post


Link to post
Share on other sites
Cluq    122
Ahh..of course!

I understood it as COMPILING_TEMP_DLL_DLL should be defined in a dll header - and when this then was included in the exe, it got defined, and then it wouldn't work.

But I'll just define it in the project settings of my dll, or in a header that is NOT included in the exe - then it should work!

Thank you - I bow to thee knights of über-coding! ...or something along those lines ;-)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this