.. include:: header.txt ======================== Shared ctypes objects ======================== The `processing.sharedctypes` module provides functions for allocating ctypes objects from shared memory which can be inherited by child processes. (See the standard library's documentation for details of the `ctypes` package.) The functions in the module are `RawArray(typecode_or_type, size_or_initializer)` Returns a ctypes array allocated from shared memory. `typecode_or_type` determines the type of the elements of the returned array: it is either a ctypes type or a one character typecode of the kind used by the `array` module. If `size_or_initializer` is an integer then it determines the length of the array, and the array will be initially zeroed. Otherwise `size_or_initializer` is a sequence which is used to initialize the array and whose length determines the length of the array. Note that setting and getting an element is potentially non-atomic -- use Array() instead to make sure that access is automatically synchronized using a lock. `RawValue(typecode_or_type, *args)` Returns a ctypes object allocated from shared memory. `typecode_or_type` determines the type of the returned object: it is either a ctypes type or a one character typecode of the kind used by the `array` module. `*args` is passed on to the constructor for the type. Note that setting and getting the value is potentially non-atomic -- use Value() instead to make sure that access is automatically synchronized using a lock. Note that an array of `ctypes.c_char` has `value` and `rawvalue` attributes which allow one to use it to store and retrieve strings -- see documentation for `ctypes`. `Array(typecode_or_type, size_or_initializer, **, lock=True)` The same as `RawArray()` except that depending on the value of `lock` a process-safe synchronization wrapper may be returned instead of a raw ctypes array. If `lock` is true (the default) then a new lock object is created to synchronize access to the value. If `lock` is a `Lock` or `RLock` object then that will be used to synchronize access to the value. If `lock` is false then access to the returned object will not be automatically protected by a lock, so it will not necessarily be "process-safe". Note that `lock` is a keyword only argument. `Value(typecode_or_type, *args, **, lock=True)` The same as `RawValue()` except that depending on the value of `lock` a process-safe synchronization wrapper may be returned instead of a raw ctypes object. If `lock` is true (the default) then a new lock object is created to synchronize access to the value. If `lock` is a `Lock` or `RLock` object then that will be used to synchronize access to the value. If `lock` is false then access to the returned object will not be automatically protected by a lock, so it will not necessarily be "process-safe". Note that `lock` is a keyword only argument. `copy(obj)` Returns a ctypes object allocated from shared memory which is a copy of the ctypes object `obj`. `synchronized(obj, lock=None)` Returns a process-safe wrapper object for a ctypes object which uses `lock` to synchronize access. If `lock` is `None` then a `processing.RLock` object is created automatically. A synchronized wrapper will have two methods in addition to those of the object it wraps: `getobj()` returns the wrapped object and `getlock()` returns the lock object used for synchronization. Note that accessing the ctypes object through the wrapper can be a lot slower than accessing the raw ctypes object. Equivalences ============ The table below compares the syntax for creating shared ctypes objects from shared memory with the normal ctypes syntax. (In the table `MyStruct` is some subclass of `ctypes.Structure`.) ==================== ========================== =========================== ctypes sharedctypes using type sharedctypes using typecode ==================== ========================== =========================== c_double(2.4) RawValue(c_double, 2.4) RawValue('d', 2.4) MyStruct(4, 6) RawValue(MyStruct, 4, 6) (c_short * 7)() RawArray(c_short, 7) RawArray('h', 7) (c_int * 3)(9, 2, 8) RawArray(c_int, (9, 2, 8)) RawArray('i', (9, 2, 8)) ==================== ========================== =========================== Example ======= Below is an example where a number of ctypes objects are modified by a child process :: from processing import Process, Lock from processing.sharedctypes import Value, Array from ctypes import Structure, c_double class Point(Structure): _fields_ = [('x', c_double), ('y', c_double)] def modify(n, x, s, A): n.value **= 2 x.value **= 2 s.value = s.value.upper() for p in A: p.x **= 2 p.y **= 2 if __name__ == '__main__': lock = Lock() n = Value('i', 7) x = Value(ctypes.c_double, 1.0/3.0, lock=False) s = Array('c', 'hello world', lock=lock) A = Array(Point, [(1.875,-6.25), (-5.75,2.0), (2.375,9.5)], lock=lock) p = Process(target=modify, args=(n, x, s, A)) p.start() p.join() print n.value print x.value print s.value print [(p.x, p.y) for p in A] The results printed are :: 49 0.1111111111111111 HELLO WORLD [(3.515625, 39.0625), (33.0625, 4.0), (5.640625, 90.25)] .. admonition:: Avoid sharing pointers Although it is posible to store a pointer in shared memory remember that this will refer to a location in the address space of a specific process. However, the pointer is quite likely to be invalid in the context of a second process and trying to dereference the pointer from the second process may cause a crash. .. _Prev: pool-objects.html .. _Up: processing-ref.html .. _Next: connection-ref.html