How GPython works¶
Let’s suppose we have a simpliest “Hello World” GPython addon:
addons\ ─┬─ example\ ─┬─ addon.json
... ├─ python\ ─── __autorun__\ ─── __init__.py
__init__.py
:
from gmod import *
# Greeting the first player
print('Hello, ' + Player(1).nick + '!')
1. Lua Launcher¶
GPython’s Lua launcher is a regular Lua addon.
When it’s loaded by Garry’s Mod’s addon system, the launcher activates
gmcl_gpython_win32.dll
and gmsv_gpython_win32.dll
:
require 'gpython'
gmcl_gpython_win32.dll
is for the client and gmsv_gpython_win32.dll
is for the server.
2. Realms’ DLLs¶
These two DLLs call gpython_run()
in gpython.dll
.
3. Main GPython DLL: gpython.dll
¶
gpython_run()
does these preparation operations:
Server¶
- Adds
luastack
module to the builtin initialization table. - Initializes Python interpreter.
- Appends
garrysmod\gpython\
tosys.path
. - Calls
setup()
inluastack
thus setting the global lua stack pointer and settingluastack.IN_GMOD
toTrue
. - Redirects I/O to Garry’s Mod console with
gmod.streams
. - Adds Lua2Python interoperability functions (using Python from Lua).
- Scans
addons\
directory for GPython addons and runs their code.
Client¶
Client’s routine is the same as server’s except the step 2.
Instead of initializing Python again, a subinterpreter is created and swapped to.
4. GPython wrappers¶
Player
is just a wrapper over the corresponding Lua functions,
as much as many other GPython services.
In this example, Player(1)
creates an object that wraps Player
Lua class. nick
is a property that
gets players’ nicknames using Player:Nick() function.
This property looks like this:
@property
def nick(self):
return str(self._player_luaobj['Nick']())
The Player
internally uses gmod.lua.LuaObject
to work with players.
5. gmod.lua
module¶
gmod.lua
module is itself a wrapper over luastack
module. gmod.lua
simplifies the interoperability
with Lua by providing LuaObject
class and G
singleton.
LuaObject
internally uses the luastack module.
6. luastack
module¶
luastack module manipulates the Lua stack. Lua stack pointer is previously set by the C++ module.
And that’s it, our GPython addon is initialized. For me, Hello, Protocs!
will be printed to console.