Shared libraries¶
This page explains how a d/Python program calls code that lives in a separate, shared file, and how the libraries d/Python itself depends on travel with your program. After it you will know how to call a library, which kinds of arguments work today, and which kinds are not yet supported.
A d/OS shared library is a file, .dbl, with a published table of the functions it exports. A d/Python program calls those functions by name with exact argument types, and the compiled program records the exact hash of every library it uses, so it only ever runs against the bytes it was built with. A library may be written in d/BASIC, d/OS's other language, which shares the same runtime, or in d/Python, and used from the other, because both follow the same published calling convention.
Calling an export¶
# fragment: lib/example.math.dbl beside the source
import dos
answer = dos.library("example.math", "Twice", 21) # BYVAL LONG -> LONG
counter = dos.array("i16", [7])
dos.library("example.math", "Bump", counter) # BYREF INTEGER: element zero
print(answer, counter[0])
Put compiled .dbl files in a lib/ folder beside your source. Three kinds of argument work today: scalars passed by value (BYVAL), single cells passed by reference (BYREF), and fixed-size arrays the library changes in place. An array parameter takes a dos.array buffer and works on it directly rather than on a copy. Libraries your program does not use are left out of the compiled output.
The libraries Python brings with it¶
Some of what makes Python work in d/Python is itself library code: dpython.integers, dpython.bits, dpython.text and dpython.numbers are ordinary shared libraries, written in d/BASIC. A program links only the ones it uses, and the compiled program file, .dbc, names each with its hash; fibonacci.py links dpython.integers and nothing else. A build writes the needed .dbl files into lib/ beside the output; the browser build returns them together with the program; and the d/OS runtime, the program that runs your compiled code, declines to start, before any output, if one is missing or altered.
The ownership rules¶
Where a call crosses into a library, the argument types must match the published signature exactly. Some things are not yet supported. Libraries whose functions can resize, erase, copy or swap arrays are declined until the runtime can keep Python's aliasing rules intact across such a call. Exports that take or return objects, opaque handles or constants also wait on future support. A Python object and a d/BASIC class are not interchangeable, so a call that would need one to stand in for the other fails with a clear message rather than working approximately. The tests cover callbacks, arguments the library changes, ownership, cleanup and failures, not only simple calls that return a number.
Widgets¶
The user-interface engine and the widget library are the same ones d/BASIC uses. As that interface settles, d/Python gets Python-flavored names, defaults and thin wrappers over the same exports; it never duplicates the widget code. Today's retained widgets example drives the engine through UI intents directly.
Identity¶
The tests for shared libraries call scalar functions, pass reference cells, fixed arrays and binary string results, check the exact signature and hash every time, and include deliberate failures: changing one byte in a library is enough for the runtime to decline it. A package file's name and a library's published name are two separate things. See Packaging for how libraries travel with an application.