Using GMod specific functions in C++ module

I’m aware that you can use the Source engine by using the Source SDK but how would I use GMod own functions (like the ones in lua_shared.dll)?

What functions?

This is how you’d call functions on the lua stack :



LUA->GetField( L, LUA_GLOBALS_INDEX, "print" );
LUA->PushString( L, "hello world!" );
LUA->Call( L, 1, 0 );


I mean engine functions that are GMod specific (not in Source SDK). The ones found in DLLs/DYLIBs/SOs.

Such as?

isn’t this what sigscanning and stuff is about?

Pretty much all of the ones he might want to call are exported or virtual, so sigscanning isn’t necessary. An example of what you might want to call would be helpful, as oubliette said.

-snip ninja’d-

Bo said as an example; functions from lua_shared, which are mostly exported and would be easier to get with GetProcAddress.

Some functions you can get because they’re exported, some you can get using interfaces and the SDK headers, some you can get using interfaces, but you’ll need to use VIndices because headers either don’t exist or are outdated. Which brings be back to what I said earlier, what functions?

Slightly related, does anyone know how I could perform a function call like this in c++?


print(CurTime())

[editline]17th July 2013[/editline]

I thought I would update my post, because this is amusing (at least to me), and because I’m sure Oubliette will laugh at me when he reads this later… :v:

I am not the type to give up and wait, so I decided to keep trying to get that above function call to work. I tried all sorts of fun combinations, like this.



    LUA->PushSpecial(SPECIAL_GLOB);
    LUA->GetField(-1, "Print");
    LUA->PushSpecial(SPECIAL_GLOB);
    LUA->GetField(-1, "CurTime");
    LUA->Call(0, 1);
    LUA->Call(1, 0);
    LUA->Pop();


After a bunch of different variations of code and different things I thought would work, I asked myself, “what is my main problem here”. I began to realize that it was the fact that I couldn’t see the stack clearly in my head. So, after a little bit of brainstorming, I wrote this:



    Msg("-----------------------------------------------
");
    Msg("Dumping da stack:
");
    for (int i=-6; i<0; i++)
    {
        int t = LUA->GetType(i);
        switch (t)
        {
        case Type::NIL:
            Msg("   %i: nil
", i); break;
        case Type::STRING:
            Msg("   %i: str: %s
", i, LUA->GetString(i)); break;
        case Type::NUMBER:
            Msg("   %i: int: %i
", i, LUA->GetNumber(i)); break;
        default:
            Msg("    %i: %s
", i, LUA->GetTypeName(i));
        }
    }
    Msg("-----------------------------------------------
");


This produces output similar to this:




-----------------------------------------------
Dumping da stack:
   -6: int: 1184371656
   -5: str: c:\program files (x86)\steam\steamapps\common\garrysmod\garrysmod\lua\bin\gmcl_cuntsmasher_win32.dll
    -4: (null)
   -3: str: LED:G | Semi Serious | Coders needed | 30+ Jobs |Staff Needed 
    -2: �D$�
    -1: �D$�
-----------------------------------------------


I then began to execute each thing one at a time.
I knew that CurTime would be hard to find on the stack, so I decided to pick another global function that output something noticeable; GetHostName().

I started with this code



    LUA->PushSpecial(SPECIAL_GLOB);
    LUA->GetField(-1, "GetHostName");
    LUA->Call(0, 1);


and dumped the stack at the end just to make sure it pushed a value. It did, so I then did this



    LUA->PushSpecial(SPECIAL_GLOB);
    LUA->GetField(-1, "GetHostName");
    LUA->Call(0, 1);
    LUA->PushSpecial(SPECIAL_GLOB);
    LUA->GetField(-1, "print");


And dumped the stack to see where that string ended up (the above stack dump example is what resulted)

At this point, I had no idea how I was going to get that string at -3 down to -1 so I could use it as an argument and call print, but fortunately I can use google.

Found this function, which I assumed garry renamed to just a plain Push. Sure enough, Push(-3) copied the string down to where I needed it.



-----------------------------------------------
Dumping da stack:
   -6: str: c:\program files (x86)\steam\steamapps\common\garrysmod\garrysmod\lua\bin\gmcl_cuntsmasher_win32.dll
    -5: (null)
   -4: str: LED:G | Semi Serious | Coders needed | 30+ Jobs |Staff Needed 
    -3: (null)
    -2: �D$�
   -1: str: LED:G | Semi Serious | Coders needed | 30+ Jobs |Staff Needed 
-----------------------------------------------


Jackpot! Now all to do is call it!

Yay! It worked! (45 minutes later :suicide:)

Now all that’s left to do is clear those three leftovers still on the stack with a simple Pop(3).

Here’s the full source (when I finally got it working, I could have sworn I had typed the exact same thing during my initial blind attempts). I feel kinda bad posting it, because it looks so easy… Oh well, at least I learned something! Maybe this will help someone else in the future who is in my shoes.



    LUA->PushSpecial(SPECIAL_GLOB);
    LUA->GetField(-1, "GetHostName");
    LUA->Call(0, 1);
    LUA->PushSpecial(SPECIAL_GLOB);
    LUA->GetField(-1, "print");
    LUA->Push(-3);
    LUA->Call(1, 0);
    LUA->Pop(3);


Some of that is unnecessary; You only need to push the global table once and pushing the print function to the stack before GetHostName removes the need to do any copying of stack values.


LUA->PushSpecial(SPECIAL_GLOB);
LUA->GetField(-1, "print");
LUA->GetField(-2, "GetHostName");
LUA->Call(0, 1);
LUA->Call(1, 0);
LUA->Pop();

When I tried that, it complained about me calling a nil value or a table value or something.

[editline]17th July 2013[/editline]

Oh nvm, didn’t see the -2 there.

-snip-