///////////////////////////////////////////////////////////////////// // Loader.cpp - Demonstrate loading "Reflection" Library // // // // Language: Visual Studio 2005 C++ // // Platform: Dell Dimension 9150, Windows XP Pro, SP 2 // // Application: Prototype for CSE687 Project #4b - Reflection // // Author: Jim Fawcett, CST 2-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// #include // note: no reflection.h included here #include #include void main() { std::cout << "\n Test Reflector Loader"; std::cout << "\n =======================\n"; ///////////////////////////////////////////////////////// // load ReflectionProto.dll library HMODULE hmod = LoadLibrary(L"ReflectionProto"); if(!hmod) { std::cout << "\n library load failed"; return; } ///////////////////////////////////////////////////////// // find global function const char* GetTypes() typedef const char* (*GT)(); GT GetTypes = (GT)GetProcAddress(hmod,"GetTypes"); if(!GetTypes) { std::cout << "\n GetProcAddress failed for GetTypes"; return; } std::cout << GetTypes(); ///////////////////////////////////////////////////////// // find const char* GetMethods(const char* type) typedef const char* (*GM)(const char*); GM GetMethods = (GM)GetProcAddress(hmod,"GetMethods"); if(!GetMethods) { std::cout << "\n GetProcAddress failed"; return; } std::cout << GetMethods("reflector"); ///////////////////////////////////////////////////////// // find const char* GetParams(const char* type, const char* method) typedef const char* (*GP)(const char*, const char*); GP GetParams = (GP)GetProcAddress(hmod,"GetParams"); if(!GetParams) { std::cout << "\n GetProcAddress failed"; return; } std::cout << GetParams("reflector","show"); FreeLibrary(hmod); std::cout << std::endl; } #ifndef REFLECTION_H #define REFLECTION_H ///////////////////////////////////////////////////////////////////// // reflection.h - Getting started with reflection mechanism // // // // Language: Visual Studio 2005 C++ // // Platform: Dell Dimension 9150, Windows XP Pro, SP 2 // // Application: Prototype for CSE687 Project #4b - Reflection // // Author: Jim Fawcett, CST 2-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// #include #include #include #include /////////////////////////////////////////////////////////// // Telling Windows to export definitions from this module // // Note: the library project defines DLL_LIB, users don't #ifdef DLL_LIB #define REFLAPI _declspec(dllexport) #else #define REFLAPI _declspec(dllimport) #endif /////////////////////////////////////////////////////////// // Defining a data structure to hold reflection information typedef std::set sets; typedef std::multiset msets; typedef std::list Params; // order is important typedef std::multimap Methods; // overloads typedef std::map Types; // types are unique /////////////////////////////////////////////////////////// // The reflector class does all the work class REFLAPI reflector { public: reflector(); virtual ~reflector() {} sets getTypes(); msets getMethods(const std::string& type); Params getParams(const std::string& type, const std::string& method); template std::string show(const std::string& msg, const T& stuff); protected: Types types; }; /////////////////////////////////////////////////////////// // Define global C functions to get unmangled names extern "C" { REFLAPI const char* GetTypes(); } extern "C" { REFLAPI const char* GetMethods(const char* type); } extern "C" { REFLAPI const char* GetParams(const char* type, const char* method); } #endif ///////////////////////////////////////////////////////////////////// // reflection.cpp - Getting started with reflection mechanism // // // // Language: Visual Studio 2005 C++ // // Platform: Dell Dimension 9150, Windows XP Pro, SP 2 // // Application: Prototype for CSE687 Project #4b - Reflection // // Author: Jim Fawcett, CST 2-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// #include #include #include "reflection.h" /////////////////////////////////////////////////////////// // Global functions with C types to make dynamic loading // simple // //----< return string with all types seperated by spaces >----------- const char* GetTypes() { reflector ref; static std::string temp = ref.show("Types",ref.getTypes()); return temp.c_str(); } //----< return string with all methods of given type >--------------- const char* GetMethods(const char* type) { std::string msg = "Methods of "; msg += type; reflector ref; static std::string temp = ref.show(msg,ref.getMethods(type)); return temp.c_str(); //reflector().getTypes(); } //----< return string with all parameters of given type & method >--- const char* GetParams(const char* type, const char* method) { std::string msg = "Parameters of "; msg += type; msg += "::"; msg += method; reflector ref; static std::string temp = ref.show(msg,ref.getParams(type,method)); return temp.c_str(); } // //----< here is where the type information is stored >--------------- // // Analyzers will have to collect type information and add to this // store. Perhaps you can think of a better way. reflector::reflector() { Params ptemp1; ptemp1.push_back("void"); Params ptemp2; ptemp2.push_back("const std::string&"); Params ptemp3; ptemp3.push_back("const std::string&"); ptemp3.push_back("const std::string&"); Params ptemp4; ptemp4.push_back("const std::string&"); ptemp4.push_back("const T&"); Methods mtemp1; mtemp1.insert(std::pair("reflector",ptemp1)); mtemp1.insert(std::pair("~reflector",ptemp1)); mtemp1.insert(std::pair("getTypes",ptemp1)); mtemp1.insert(std::pair("getMethods",ptemp2)); mtemp1.insert(std::pair("getParams",ptemp3)); mtemp1.insert(std::pair("show",ptemp4)); types["reflector"] = mtemp1; } // //----< return a set of types >-------------------------------------- sets reflector::getTypes() { sets temp; Types::iterator iter; for(iter=types.begin(); iter!=types.end(); ++iter) temp.insert(iter->first); return temp; } //----< return a multiset of methods - remember overloading >-------- msets reflector::getMethods(const std::string& type) { msets temp; Methods::iterator iter; Methods& methods = types[type]; for(iter=methods.begin(); iter!=methods.end(); ++iter) temp.insert(iter->first); return temp; } //----< return a list of parameters - remember order is important >-- Params reflector::getParams( const std::string& type, const std::string& method ) { Params temp; Params::iterator iter; Methods methods = types[type]; Methods::iterator miter = methods.find(method); Params& params = (*miter).second; for(iter=params.begin(); iter!=params.end(); ++iter) temp.push_back(*iter); return temp; } //----< generate a string encoded with type information >------------ template std::string reflector::show(const std::string& msg, const T& stuff) { T::const_iterator iter; std::ostringstream out; out << "\n " << msg; for(iter=stuff.begin(); iter!=stuff.end(); ++iter) out << "\n " << (*iter).c_str(); out << "\n"; return out.str(); } // #ifdef TEST_REFLECTIONPROTO //----< test as a console application, then turn into a library >---- void main() { std::cout << "\n Test Reflector"; std::cout << "\n ================\n"; reflector* pRef = new reflector; std::cout << pRef->show("types:",pRef->getTypes()); std::cout << pRef->show("methods of reflector:",pRef->getMethods("reflector")); std::cout << pRef->show("parameters of show:", pRef->getParams("reflector","show")); delete pRef; std::cout << std::endl; }; #endif