| PRELIMINARY |
| CONCEPT |
| python |
| |
| DESCRIPTION |
| Python can be used to extend the LDMud driver. At the startup |
| of LDMud a python script will be called that can register |
| additional efuns. The python script can either be given |
| on the command line using the --python-script option, |
| or at compile time with the --with-python-script configuration |
| option. |
| |
| The python script can import the builtin ldmud module. |
| This module provides the following functions: |
| |
| - register_efun(name, function) -> None |
| Registers a new efun name. This is not allowed during |
| compilation of an LPC object. |
| |
| If the Python function has type annotations for its |
| arguments and return value, the type is checked |
| at compile and runtime. Union types can be specified |
| as tuples of types. |
| |
| - unregister_efun(name) -> None |
| Removes a python efun from registration. This is not |
| allowed during compilation of an LPC object. The |
| removal will only affect newly compiled code, |
| already compiled code will produce errors when |
| calling this efun. |
| |
| - register_socket(fd, function [,eventmask]) -> None |
| Registers a socket <fd> to watch for events (like |
| poll/select). The socket must be either given as |
| an integer or an object with a fileno() method |
| returning an integer. The function must be a callable |
| accepting one argument, the actual event mask. |
| <eventmask> may be an combination of select.POLLIN, |
| select.POLLOUT and select.POLLPRI or a callable |
| returning such a combination. |
| |
| - unregister_socket(fd) -> None |
| Removes a previously registered socket from the |
| watch list. |
| |
| - register_hook(hook, function) -> None |
| Register a hook. The python function will be called |
| whenever <hook> happens. <hook> can be one of the |
| following: |
| |
| ON_HEARTBEAT |
| Called without arguments for every backend loop |
| |
| ON_OBJECT_CREATED |
| Called whenever an object was created, with the |
| object as its first and only argument. This call |
| happens before any LPC code of the object ran. |
| |
| ON_OBJECT_DESTRUCTED |
| Called just before an object will be destructed, |
| with the object as its first and only argument. |
| |
| - unregister_hook(hook, function) -> None |
| Removes a hook function. |
| |
| - get_master() - > Object |
| Returns the current master object. |
| Returns None, if there is no master object (yet). |
| |
| - get_simul_efun() - > Object |
| Returns the current simul-efun object |
| (or None if there is none). |
| |
| |
| This module provides the following types: |
| |
| - Object(filename) |
| Corresponds to the LPC object type. |
| On instantiation a filename for an object |
| to search or load is required. |
| |
| - Array([values | size]) |
| Corresponds to an LPC array. |
| Can either be initialized with a list of values |
| or to a given size. |
| |
| Supports element access with [], len() and __contains__. |
| |
| - Mapping([values | width]) |
| Corresponds to an LPC mapping. |
| Can either be initialized with a dict, a list of tuples |
| or as an empty mapping with a given width. |
| |
| Supports element access with [], len(), __contains__ |
| and has a width member. |
| |
| - Struct(object, name [, values]) |
| Corresponds to an LPC struct. |
| On initialization the name of the struct definition and |
| the correspopnding object is required. It can be initialized |
| with a list of values or dict. |
| |
| Supports member access as regular python members. |
| |
| - Closure(object [,name [, lfun_object]]) |
| Corresponds to an LPC closure. |
| On initialization a closure bound to <object> will be created, |
| like a call to symbol_function(<name> [, <lfun_object>]). |
| |
| Supports function calls. |
| |
| - Symbol(name [, quotes]) |
| Corresponds to an LPC symbol. |
| On initialization the name of the symbol is required. |
| Optionally the number of quotes (at least 1) can be specified. |
| |
| Has two members: name and quotes. |
| |
| - QuotedArray(array [, quotes]) |
| Corresponds to an LPC quoted array. |
| On initialization an array is required. |
| Optionally the number of quotes (at least 1) can be specified. |
| |
| Has two members: array and quotes. |
| |
| |
| This module contains the following sub-namespaces: |
| |
| - efuns |
| This namespace contains all original efuns (without any |
| registered python efuns or simul-efuns). These can be called |
| as a regular function. |
| |
| |
| EXAMPLE |
| import ldmud |
| |
| def hello_world(name: str) -> int: |
| print("Hello, world, %s!\n" % (name,)) |
| return 1 |
| |
| ldmud.register_efun("hello", hello_world) |
| |
| NOTES |
| Just like simul-efuns python efuns can shadow real efuns. The |
| original efun is then inaccessible for LPC code (except for code |
| that was compiled before the efun was registered). Python efuns are |
| nearly indistinguishable from real efuns, they also use the efun:: |
| prefix. However they can be detected with |
| CLOSURE_IS_PYTHON_EFUN(get_type_info(#'efun,1)) |
| |
| Without the prefix the order of name resolution for function calls is: |
| 1. lfuns |
| 2. simul-efuns |
| 3. python efuns |
| 4. real efuns |
| |
| Also just like simul-efuns python-registered efuns are called |
| from LPC code that was compiled after the registration. LPC code |
| that was compiled before the registration will still call the |
| original efuns (or throw a compile error if that efun doesn't exist). |
| Therefore such efuns should be registered in the python startup |
| script. |
| |
| When a python efun is unregistered, code that was compiled while the |
| registration was in effect will throw a runtime error. (Regardless |
| of whether a driver efun with the same name exists or not.) |
| |
| There is a limit of 2048 python efuns. Not only registered, but also |
| formerly registered - but now unregistered - efuns count toward that |
| limit. Re-registering the same efun name again won't count a second |
| time. (LPC code that was compiled during the previous registration |
| will also call the new efun after the re-registration.) |
| |
| As LDMud is single-threaded, the python code will run in the same |
| thread as the LPC machine. So any long-running python function will |
| halt the MUD for all players. Hence python functions should return |
| promptly and source out any lengthy tasks to another process. If |
| other threads are spawned from python, then these threads are not |
| allowed to access any LDMud functions or objects. |
| |
| Finally a note of caution: Don't change the meaning of base efuns |
| fundamentally as it furthers confusion and hinders exchange of LPC |
| code and knowledge between mudlibs. |
| |
| HISTORY |
| LDMud 3.5 implemented the python functionality. |
| LDMud 3.6 added type checks. |
| |
| SEE ALSO |
| simul_efun(C) |