Zesstra | 7ea4a03 | 2019-11-26 20:11:40 +0100 | [diff] [blame] | 1 | PRELIMINARY |
| 2 | CONCEPT |
| 3 | python |
| 4 | |
| 5 | DESCRIPTION |
| 6 | Python can be used to extend the LDMud driver. At the startup |
| 7 | of LDMud a python script will be called that can register |
| 8 | additional efuns. The python script can either be given |
| 9 | on the command line using the --python-script option, |
| 10 | or at compile time with the --with-python-script configuration |
| 11 | option. |
| 12 | |
| 13 | The python script can import the builtin ldmud module. |
| 14 | This module provides the following functions: |
| 15 | |
| 16 | - register_efun(name, function) -> None |
| 17 | Registers a new efun name. This is not allowed during |
| 18 | compilation of an LPC object. |
| 19 | |
| 20 | If the Python function has type annotations for its |
| 21 | arguments and return value, the type is checked |
| 22 | at compile and runtime. Union types can be specified |
| 23 | as tuples of types. |
| 24 | |
| 25 | - unregister_efun(name) -> None |
| 26 | Removes a python efun from registration. This is not |
| 27 | allowed during compilation of an LPC object. The |
| 28 | removal will only affect newly compiled code, |
| 29 | already compiled code will produce errors when |
| 30 | calling this efun. |
| 31 | |
| 32 | - register_socket(fd, function [,eventmask]) -> None |
| 33 | Registers a socket <fd> to watch for events (like |
| 34 | poll/select). The socket must be either given as |
| 35 | an integer or an object with a fileno() method |
| 36 | returning an integer. The function must be a callable |
| 37 | accepting one argument, the actual event mask. |
| 38 | <eventmask> may be an combination of select.POLLIN, |
| 39 | select.POLLOUT and select.POLLPRI or a callable |
| 40 | returning such a combination. |
| 41 | |
| 42 | - unregister_socket(fd) -> None |
| 43 | Removes a previously registered socket from the |
| 44 | watch list. |
| 45 | |
| 46 | - register_hook(hook, function) -> None |
| 47 | Register a hook. The python function will be called |
| 48 | whenever <hook> happens. <hook> can be one of the |
| 49 | following: |
| 50 | |
| 51 | ON_HEARTBEAT |
| 52 | Called without arguments for every backend loop |
| 53 | |
| 54 | ON_OBJECT_CREATED |
| 55 | Called whenever an object was created, with the |
| 56 | object as its first and only argument. This call |
| 57 | happens before any LPC code of the object ran. |
| 58 | |
| 59 | ON_OBJECT_DESTRUCTED |
| 60 | Called just before an object will be destructed, |
| 61 | with the object as its first and only argument. |
| 62 | |
| 63 | - unregister_hook(hook, function) -> None |
| 64 | Removes a hook function. |
| 65 | |
| 66 | - get_master() - > Object |
| 67 | Returns the current master object. |
| 68 | Returns None, if there is no master object (yet). |
| 69 | |
| 70 | - get_simul_efun() - > Object |
| 71 | Returns the current simul-efun object |
| 72 | (or None if there is none). |
| 73 | |
| 74 | |
| 75 | This module provides the following types: |
| 76 | |
| 77 | - Object(filename) |
| 78 | Corresponds to the LPC object type. |
| 79 | On instantiation a filename for an object |
| 80 | to search or load is required. |
| 81 | |
| 82 | - Array([values | size]) |
| 83 | Corresponds to an LPC array. |
| 84 | Can either be initialized with a list of values |
| 85 | or to a given size. |
| 86 | |
| 87 | Supports element access with [], len() and __contains__. |
| 88 | |
| 89 | - Mapping([values | width]) |
| 90 | Corresponds to an LPC mapping. |
| 91 | Can either be initialized with a dict, a list of tuples |
| 92 | or as an empty mapping with a given width. |
| 93 | |
| 94 | Supports element access with [], len(), __contains__ |
| 95 | and has a width member. |
| 96 | |
| 97 | - Struct(object, name [, values]) |
| 98 | Corresponds to an LPC struct. |
| 99 | On initialization the name of the struct definition and |
| 100 | the correspopnding object is required. It can be initialized |
| 101 | with a list of values or dict. |
| 102 | |
| 103 | Supports member access as regular python members. |
| 104 | |
| 105 | - Closure(object [,name [, lfun_object]]) |
| 106 | Corresponds to an LPC closure. |
| 107 | On initialization a closure bound to <object> will be created, |
| 108 | like a call to symbol_function(<name> [, <lfun_object>]). |
| 109 | |
| 110 | Supports function calls. |
| 111 | |
| 112 | - Symbol(name [, quotes]) |
| 113 | Corresponds to an LPC symbol. |
| 114 | On initialization the name of the symbol is required. |
| 115 | Optionally the number of quotes (at least 1) can be specified. |
| 116 | |
| 117 | Has two members: name and quotes. |
| 118 | |
| 119 | - QuotedArray(array [, quotes]) |
| 120 | Corresponds to an LPC quoted array. |
| 121 | On initialization an array is required. |
| 122 | Optionally the number of quotes (at least 1) can be specified. |
| 123 | |
| 124 | Has two members: array and quotes. |
| 125 | |
| 126 | |
| 127 | This module contains the following sub-namespaces: |
| 128 | |
| 129 | - efuns |
| 130 | This namespace contains all original efuns (without any |
| 131 | registered python efuns or simul-efuns). These can be called |
| 132 | as a regular function. |
| 133 | |
| 134 | |
| 135 | EXAMPLE |
| 136 | import ldmud |
| 137 | |
| 138 | def hello_world(name: str) -> int: |
| 139 | print("Hello, world, %s!\n" % (name,)) |
| 140 | return 1 |
| 141 | |
| 142 | ldmud.register_efun("hello", hello_world) |
| 143 | |
| 144 | NOTES |
| 145 | Just like simul-efuns python efuns can shadow real efuns. The |
| 146 | original efun is then inaccessible for LPC code (except for code |
| 147 | that was compiled before the efun was registered). Python efuns are |
| 148 | nearly indistinguishable from real efuns, they also use the efun:: |
| 149 | prefix. However they can be detected with |
| 150 | CLOSURE_IS_PYTHON_EFUN(get_type_info(#'efun,1)) |
| 151 | |
| 152 | Without the prefix the order of name resolution for function calls is: |
| 153 | 1. lfuns |
| 154 | 2. simul-efuns |
| 155 | 3. python efuns |
| 156 | 4. real efuns |
| 157 | |
| 158 | Also just like simul-efuns python-registered efuns are called |
| 159 | from LPC code that was compiled after the registration. LPC code |
| 160 | that was compiled before the registration will still call the |
| 161 | original efuns (or throw a compile error if that efun doesn't exist). |
| 162 | Therefore such efuns should be registered in the python startup |
| 163 | script. |
| 164 | |
| 165 | When a python efun is unregistered, code that was compiled while the |
| 166 | registration was in effect will throw a runtime error. (Regardless |
| 167 | of whether a driver efun with the same name exists or not.) |
| 168 | |
| 169 | There is a limit of 2048 python efuns. Not only registered, but also |
| 170 | formerly registered - but now unregistered - efuns count toward that |
| 171 | limit. Re-registering the same efun name again won't count a second |
| 172 | time. (LPC code that was compiled during the previous registration |
| 173 | will also call the new efun after the re-registration.) |
| 174 | |
| 175 | As LDMud is single-threaded, the python code will run in the same |
| 176 | thread as the LPC machine. So any long-running python function will |
| 177 | halt the MUD for all players. Hence python functions should return |
| 178 | promptly and source out any lengthy tasks to another process. If |
| 179 | other threads are spawned from python, then these threads are not |
| 180 | allowed to access any LDMud functions or objects. |
| 181 | |
| 182 | Finally a note of caution: Don't change the meaning of base efuns |
| 183 | fundamentally as it furthers confusion and hinders exchange of LPC |
| 184 | code and knowledge between mudlibs. |
| 185 | |
| 186 | HISTORY |
| 187 | LDMud 3.5 implemented the python functionality. |
| 188 | LDMud 3.6 added type checks. |
| 189 | |
| 190 | SEE ALSO |
| 191 | simul_efun(C) |