views:

302

answers:

4

How can I make equivalents to these methods in C? I read somewhere that they could be "replaced with functions that take a structure pointer as the first parameter," but I'm not sure how to do this, if that is the right thing to do.

struct SCustomKeys
{
    struct SCustomKey Save[10];
    struct SCustomKey Load[10];
    struct SCustomKey Slot[10];

    struct SCustomKey PrintScreen;
    struct SCustomKey LastItem; // dummy, must be last

    //--methods--
    struct SCustomKey &key(int i) { return ((SCustomKey*)this)[i]; }
    struct SCustomKey const &key(int i) const { return ((SCustomKey*)this)[i]; }
};

Here's an example of how they are used:

void ZeroCustomKeys (SCustomKeys *keys)
{
    int i = 0;

    SetLastCustomKey(&keys->LastItem);
    while (!IsLastCustomKey(&keys->key(i))) {
     keys->key(i).key = 0;
     keys->key(i).modifiers = 0;
     i++;
    };
}

More context: http://pastebin.com/m649210e8

Thanks for the help. I haven't been able to the suggested replacement for the C++ method working with this function yet though. Any ideas on how to approach this?

void InitCustomKeys (struct SCustomKeys *keys)
{
    UINT i = 0;

    SetLastCustomKey(&keys->LastItem);
    while (!IsLastCustomKey(&keys->key(i))) {
     SCustomKey &key = keys->key(i);
     key.key = 0;
     key.modifiers = 0;
     key.handleKeyDown = NULL;
     key.handleKeyUp = NULL;
     key.page = NUM_HOTKEY_PAGE;
     key.param = 0;
     i++;
    };

    //an example key
    keys->PrintScreen.handleKeyDown = HK_PrintScreen;
    keys->PrintScreen.code = "PrintScreen";
    keys->PrintScreen.name = L"Print Screen";
    keys->PrintScreen.page = HOTKEY_PAGE_MAIN;
    keys->PrintScreen.key = VK_PAUSE;
}

And the new function I'm trying now is:

 struct SCustomKey* key(struct SCustomKeys *scs, int i) { 
    return &(((SCustomKey*)scs)[i]); 
 }
+4  A: 
 struct SCustomKey &key(int i) { return ((SCustomKey*)this)[i]; }
 struct SCustomKey const &key(int i) const {
     return ((SCustomKey*)this)[i]; 
 }

will become

 struct SCustomKey* key(struct SCustomKeys *scs, int i) { 
    /* Shouldn't you be using one of Load/Save/... arrays? */
    return &(((SCustomKey*)scs)[i]); 
 }

C does not have const functions. So, only one version.

dirkgently
If you look at his code, he's editing the return value (since he's returning a reference to a SCustomKey). Wouldn't he need a pointer returned in order to handle that correctly in C?
Reed Copsey
You would probably name it something more descriptive than "key" to avoid name conflicts. And you'd return by pointer since the original returned by reference. And if you wanted to make a const version you'd jast name it "*_const".
Greg Rogers
@Greg: You don't gain much with such a construct in C.
dirkgently
@Reed Copsey: Probably. I'll update.
dirkgently
A: 

The idea is that you would pass in a pointer to an SCustomKeys as the first (well, it doesn't really matter; it could be any) parameter, and use it in place of "this".

Adam Jaskiewicz
+5  A: 

Basically, instead of having a member function like:

struct SCustomKey &key(int i) { return ((SCustomKey*)this)[i]; }

You will need to rewrite this as a function that takes a pointer to a SCustomKeys as it's first argument.

The function will look like:

SCustomKey* key(SCustomKeys* customKeys, int i) 
{ return ((SCustomKey*)(customKeys)+i); }

This should provide you with a pointer to the element you are trying to access.

Reed Copsey
Mention that this usage of SCustomKey will require a typedef.
dirkgently
Good point - I almost always typedef my structs, so I forgot to mention that.
Reed Copsey
+1  A: 
Nathan Fellman
You can fake the const version by returning copied structs instead of pointers: struct SCustomKey key_const(struct SCustomKey* this, int i) { return ((SCustomKey*)this)[i]; }
jmucchiello