In dit geval werkt het niet
Waarbij deze code een "ApplicationSetting" string uit een Xml file haalt
C++:
1
2
3
4
5
6
7
8
9
10
| DeserialisableSetting* setting = (DeserialisableSetting*)ObjectFactory::getInstance().createObject(element->Value());
if (setting && setting->m_rttiInfo.IsDerived(DeserialisableSetting::m_rttiInfo))
{
setting->deserialise(element);
SettingsManager::getInstance().setSetting(setting);
}
else
{
DLTRACEERRORC(m_errorLog, "Couldn't create setting for: %s, make sure there is a known class for this setting", element->Value());
} |
De functie om een om een object te creeeren is
C++:
1
2
3
4
5
6
7
8
9
| void* createObject(const String& className)
{
objectCreationFunction* creator = ClassRegistrySingleton::getInstance().getCreationFuntion(className.getString());
if (creator)
{
return (**creator)();
}
return 0;
} |
Dit is de code om een creation function te krijgen
C++:
1
2
3
4
5
6
7
8
9
| objectCreationFunction* getCreationFuntion(std::string classID)
{
STROCFIT iterator = m_strOCFs.find(classID);
if (iterator != m_strOCFs.end())
{
return &iterator->second;
}
return 0;
} |
Deze klasse wordt geprobeert om aan te maken
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| class ApplicationSetting : public DeserialisableSetting
{
DL_DECLARE_CLASS(ApplicationSetting, DeserialisableSetting)
public:
ApplicationSetting();
~ApplicationSetting();
void deserialise(TiXmlElement* element);
protected:
private:
String m_appName;
String m_windowName;
};
in CPP
DL_IMPLEMENT(ApplicationSetting, DeserialisableSetting); |
Deze macros zijn vereenvoudigd zodat alleen het ClassRegistration gedeelte te zien is met de daar bijhoorende code
C++:
1
2
3
4
5
6
7
8
| #define DL_DECLARE_CLASS(CLASS, BASECLASS) \
public:\
typedef BASECLASS Super;\
static const ClassRegistrator s_registration##CLASS;\
static CLASS* CreateObject() { return new CLASS(); }
#define DL_IMPLEMENT(CLASS, BASECLASS)\
const ClassRegistrator CLASS::s_registration##CLASS(&CLASS::m_rttiInfo, #CLASS, &ObjectFactory::objectCreationFunctionTemplate<CLASS>) |
De registratie wordt hierdoor gedaan:
C++:
1
2
3
4
5
6
7
8
| class ClassRegistrator
{
public:
ClassRegistrator(const RTTI* classType, const char* classID, objectCreationFunction ocf)
{
ClassRegistrySingleton::getInstance().addRegistration(classType, classID, ocf);
}
}; |
C++:
1
2
3
4
5
| void addRegistration( const RTTI* classType, const char* classID, objectCreationFunction ocf)
{
m_rttiOCFs.insert(RTTIOCFPAIR(classType, ocf));
m_strOCFs.insert(STROCFPAIR(classID, ocf));
} |
Wat er gebeurt tijdens runtime is dat setting altijd een nulpointer is. De code om een settings file in te lezen gebeurt tijdens de initialisatie van de applicatie, en als ik het goed begrijp is dit nadat alle class statics zijn gecreerd.
Als ik een debug run doe en kijk wanneer addRegistration wordt aangeroepen voor class waarbij het werkt gebreurt dit voordat main van de applicatie wordt aangeroepen, ik snap niet waarom dit niet voor alle objecten gebeurt want de techniek die ik probeer te gebruiken leunt daar nogal zwaar op.
Callstack voor een Object
code:
1
2
3
4
5
6
7
8
9
| > DLExampleApplication_debug.exe!ClassRegistrator::ClassRegistrator(const RTTI * classType=0x00698b50, const char * classID=0x0065d2ec, void * (void)* ocf=0x004c6bbe) Line 71 C++
DLExampleApplication_debug.exe!`dynamic initializer for 'Object::s_registrationObject''() Line 3 + 0x37 bytes C++
msvcr90d.dll!_initterm(void (void)* * pfbegin=0x00658294, void (void)* * pfend=0x00658fc8) Line 903 C
DLExampleApplication_debug.exe!__tmainCRTStartup() Line 497 + 0xf bytes C
DLExampleApplication_debug.exe!wWinMainCRTStartup() Line 399 C
kernel32.dll!754b3677()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
ntdll.dll!77039d72()
ntdll.dll!77039d45() |
Voor een RenderSetting class die niet veel anders is dan de ApplicationSetting class gaat het wel gewoon goed. Het enige verschil tussen de twee is dat RenderSetting niet in een eigen header en CPP is gedefinieerd
Na wat debuggen, kan dit te maken hebben met hoe files worden geinclude?