Accessing arbitrary variables at runtime
Hi,
This is my first post and first of all let me say thanks for all the help the gamedev community has provided regarding programming (especially OpenGL). On to my question:
I have a C++ program and I would like to be able to get and set variables while my app is running. What is a good way to provide access to program variables?
For the sake of context, this is an OpenGL app that has enough variables that binding keys, etc is impractical. I've written a little console (like a simple version of what you get in Quake, etc when you press tilde). I can enter commands to check and change variables in the console.
However, the way I've written it I have to code a separate function for each variable I want to get/set. When I parse/interpret the command line i resolve a function pointer, pass it the params and execture it. Is there some better (more general way) to do this?
I'm sure others have this type of functionality in games or other programs. What approach have you used / do you suggest?
Has anyone gone so far as to create a simple debugging environment (like a lightweight gdb) or something like an interpretive language interface, where you can call your functions directly?
Thanks in advance,
Frank.
You could do it in a general way using .Net reflection, but that obviously only works if you're using a .Net language.
You could also do it in a general way if you expose things through a scripting language and have your console execute that scripting language.
I don't have any experience exposing my code through a scripting language, though, so I don't know if there's any languages or tools that would let you automatically expose everything.
You could also store every variable you want to be able to modify in a hash table indexed by a string and have your console automatically look up the variable in the hash table.
You could also do it in a general way if you expose things through a scripting language and have your console execute that scripting language.
I don't have any experience exposing my code through a scripting language, though, so I don't know if there's any languages or tools that would let you automatically expose everything.
You could also store every variable you want to be able to modify in a hash table indexed by a string and have your console automatically look up the variable in the hash table.
For your console class I could imagine something like
And then from the console, while in the game, you could type
Console.BindInt( "PlayerX", &player->x );
And then from the console, while in the game, you could type
SET PlayerX 400
It's pretty simple to do a basic command line in the program, you could (for example) have something like std::map<std::string, boost::function<void (const std::string&)> >, then tokenize each command line by spaces and pass to the function described by the map at the first string in the command.
Hi,
Thanks for the help. .Net reflection looks pretty powerful. Alas, I'm not using .Net. I implemented a map for functions (get, set, etc) and a function to bind variables, as recommended. It's definitely better than a single function for each variable!
I'm now trying to template it to avoid creating BindFloat, BindString, etc..., and perhaps to avoid using switches in the my get/set/print... functions (and to learn about templates). I've created a function:
template <typename T>
Console.Bind(string & const name, T *ptr, boundVar_t type)
But it seems silly that I need the boundVar_t tag. Is there a better (implicit) way to keep track of the type so I can do the appropriate thing with the data later? Can T be saved directly somehow?
Thanks again,
Frank
Here's are some snippets from my current implementation:
// type tag
typedef enum {
intt, floatt, stringt // must specify every possible type :(
} type_t;
typedef struct {
string name;
type_t type;
void *ptr;
} boundVar_t;
//: Bind variable
void Console::Bind(string const &name, T *ptr, boundVar_t type)
{
boundVar_t newBind;
newBind.name = name;
newBind.type = type;
newBind.ptr = (void*) ptr;
variableList.push_back(newBind);
}
// ... somewhere in Console.Set
switch (variableList[hash].type) {
case intt:
*((int*)variableList[hash].ptr) = (int)valueParsedFromCommandline; break;
case floatt:
*((float*)variableList[hash].ptr) = (float)valueParsedFromCommandline; break;
// ...
Thanks for the help. .Net reflection looks pretty powerful. Alas, I'm not using .Net. I implemented a map for functions (get, set, etc) and a function to bind variables, as recommended. It's definitely better than a single function for each variable!
I'm now trying to template it to avoid creating BindFloat, BindString, etc..., and perhaps to avoid using switches in the my get/set/print... functions (and to learn about templates). I've created a function:
template <typename T>
Console.Bind(string & const name, T *ptr, boundVar_t type)
But it seems silly that I need the boundVar_t tag. Is there a better (implicit) way to keep track of the type so I can do the appropriate thing with the data later? Can T be saved directly somehow?
Thanks again,
Frank
Here's are some snippets from my current implementation:
// type tag
typedef enum {
intt, floatt, stringt // must specify every possible type :(
} type_t;
typedef struct {
string name;
type_t type;
void *ptr;
} boundVar_t;
//: Bind variable
void Console::Bind(string const &name, T *ptr, boundVar_t type)
{
boundVar_t newBind;
newBind.name = name;
newBind.type = type;
newBind.ptr = (void*) ptr;
variableList.push_back(newBind);
}
// ... somewhere in Console.Set
switch (variableList[hash].type) {
case intt:
*((int*)variableList[hash].ptr) = (int)valueParsedFromCommandline; break;
case floatt:
*((float*)variableList[hash].ptr) = (float)valueParsedFromCommandline; break;
// ...
Im not sure what you were looking to do, How about you wrap the variables themselves in templates, some sort of convinance class.
template<class T>class BindVar{ BindVar(std::string, *T); Get(); Set(T); T *item}// Usageint *variable_to_bind = myengine::getvar();BindVar<int> bv = new BindVar<int>("Master", variable_to_bind);Console::Get().AddToHash(bv)
Hi,
When etothex originally mentioned boost, I didin't look at it very carefully. I've now read the tutorials. It looks very useful, thanks snk_kid. I'll try it your way first, Paul, then I'll try boost.
Thanks again,
Frank
When etothex originally mentioned boost, I didin't look at it very carefully. I've now read the tutorials. It looks very useful, thanks snk_kid. I'll try it your way first, Paul, then I'll try boost.
Thanks again,
Frank
Quote:Original post by snk_kid
I suggest investigating boost libraries, in particular Boost.Variant.
Oh, hell yes!
I like to think that I have a bit of experience in this as I've spent the last month and a half writing my console, and I'm just finishing it up for functions.
For variables, I'm using boost::variant, and I'm storing them in a std::map<std::string, boost::variant> object. The variant can be a pointer, and I've created the visitors, so when it is a pointer, it's de-referenced and value it points to is get or set.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement