# DYNLIB

> [HTML Version](dynlibsbr.htm)

_Updated October 2021; see History_

To load/unload an external library:

**xcall DYNLIB, dlctl \{,lib, convention, stackspace\}**

To call a function in the external library:

**xcall DYNLIB, dlctl, funcsig \{,parms...\}**

(Windows and Linux only) DYNLIB provides a mechanism for A-ShellBASIC programs to dynamically access routines in external libraries written in C (or compiled to a C compatible object format), without the need for any special compile-time linking or modifications to A-Shell to support the external library. The fundamental difficulty here is the fact that third-party libraries may have many different calling conventions, and there is almost no limit to the variety of return types and parameter lists for the functions involved. DYNLIB deals with this variability by supporting a wide variety of the most common library calling conventions, and a flexible scheme for specifying function signatures so that the function arguments can be properly passed and converted.

**Parameters**

_dlctl (ST\_DYNLIBCTL)_  \[in/out\]

This is a structure containing various control parameters used and/or updated for every call. It is defined in [ashinc:dynlib.def](https://bitbucket.org/microsabio/soslib/src/master/907016/dynlib.def) as:

defstruct ST\_DYNLIBCTL

    map2 handle,DLHANDLE   \! handle to the external module

    map2 opcode,b,4        \! see DCOP\_xxx

    map2 flags,b,4         \! flags (see DLF\_xxx)

    map2 status,i,4        \! see (DYNLIBE\_xxx)

    map2 syserr,i,4        \! system error set by called fun, e.g. GetLastError() for Windows; else errno

    map2 lastfunc\$,s,64    \! function signature of last called function

endstruct



Opcodes from [ashinc:dynlib.def](https://bitbucket.org/microsabio/soslib/src/master/907016/dynlib.def) are:

| **Value** | **Symbol** |
|------|------|
| 0 | DCOP\_LOAD    |
| 1 | DCOP\_UNLOAD  |
| 2 | DCOP\_CALL    |
| 4 | [DCOP\_DEREF](dynlibindirectouput.md)   |
| 5 | DCOP\_GETREF  |




_lib_  ([String](string.md))  \[in\]

Used only for the load routine (opcode DCOP\_LOAD), _lib_ specifies the name of the external library. For Windows, this is just the DLL name (no path or extension needed, provided the DLL is in the standard search path, or in the A-Shell bin directory). For Linux, it will be a name like "libxl.so.1" which references a shared library in the system library path (typically /usr/lib). By convention, typically file in the /usr/lib directory is actually a symbolic link to the actual library file.

_convention_  ([Num](num.md))  \[in\]

Used only for the load routine to specify the calling convention for the external library. See the DLCC\_xxx codes defined in [ashinc:dynlib.def](https://bitbucket.org/microsabio/soslib/src/master/907016/dynlib.def) for the possibilities. Note that the most common options are DLCC\_C\_X86\_WIN32\_STD for Windows DLLs, and DLCC\_C\_X86\_CDECL for Linux.

_stackspace_  ([Num](num.md))  \[in\]

Used only for the load routine to specify the amount of stack space to reserve for the library. 4 to 8K is typically plenty.

_funcsig_  ([String](string.md))  \[in\]

This string is used in conjunction with a call to a library function (opcode DCOP\_CALL) to declare the function name, return type, and expected parameter list. The format is:

_funcname(pppp....)r_

where:  


•	_funcname_ is the name of the function to call in the external library

•	each p is a one letter code indicating the type of parameter from the table below

•	r indicates the return type of the function, from the table below

| **Code** | **Description** | **** | **Code** | **Description** |
|------|------|------|------|------|
| a | char \* (convert ANSI to UTF8) |  | L | 64 bit unsigned integer (x,8) |
| A | const char\* (convert ANSI to UTF8) |  | p | (lower case "p") void\*; see _Output Parameters_ below |
| B | \_Bool, bool (i,2) or i,4? |  | P | (upper case "P") similar to "p" but receives the size of a ">" argument. See _Output Parameters_ below. |
| c | char (s,1) |  | s | short (i,2) |
| C | unsigned char (s,1) |  | S | unsigned short (b,2) |
| d | double (f8) |  | u | char \* (from UTF8 string). See _Output Parameters_ below. |
| f | float (f4) |  | U | const wchar \* (from UTF8 string) |
| h | 32 or 64 bit handle (x,8) |  | v | (lower case "v") void. See _Output Parameters_ below. |
|  |  |  | V | (Upper case "V")const void \*; like Z but is converted to NULL if the corresponding parameter value is "". See _Output Parameters_ below. |
| i | int (i,4) |  | w | wchar\_t \* (s)  |
| I | unsigned int (b,4) |  | W | const wchar\_t \* (s) |
| j | long (i,4) |  | z | char \* (s,0) |
| J | unsigned long (b,4) |  | Z | const char \* (s,0) |
| l | 64 bit signed integer (x,8) |  | \> | identifies an indirect output string parameter. See [DYNLIB Indirect Output.](dynlibindirectouput.md) |




**Examples**

| **C Function Prototype** | **funcsig** |
|------|------|
| void f1(); | ”f1()v” |
| int f2(int, int); | ”f2(ii)i” |
| long long f3(void\*); | ”f3(p)L” |
| void f3(int\*\*); | ”f3(p)v” |
| double f4(int, bool, char, double, const char\*); | ”f4(iBcdZ)d” |


Following the function signature, the remaining parameters are the arguments being passed, followed by the parameter to receive the return value of the function.

**Output Parameters**

Parameters to be output or updated by the called routine should be defined using one of the **p**, **P **, **u**, **v**,** w**, or **>** codes. Codes **u** and **w** will convert ASCII / Latin1 strings used in the application to UTF8 or UNICODE-16 characters used by the called library routine, and vice versa if the parameter is updated by the routine. Code **v** is used for routines that do not return any value. See Indirect Output Parameters, for more details on the **P** and **>** codes.

**Comments**

See [LIBXL.BSI in EXLIB:\[908,68\]](https://bitbucket.org/microsabio/exlib/src/master/908068/libxl.bsi) for examples.

Because this is a bit tricky, if you have an external library you would like to interface with, you may want to consult with MicroSabio to help you evaluate it and get it started.

**History**

2021 October, A-Shell 6.5.1708:  Fully implemented types "l" and "L," added type "h." These were required to support using DYNLIB to call 64 bit library routines. The "h" (handle) option in particular is needed to allow BASIC programs to interface with libraries that rely on handles (like AXL) and which may be either 32 or 64 bit.

2019 September, A-Shell 6.5.1667:  Added type "P" which acts similarly to "p" but receives the size of a ">" argument. Useful for functions that return a pointer to a buffer in one argument and the size the buffer in another. The AXL function Fn'LibXL'GetPicture uses this technique.

2017 November, A-Shell 6.5.1621:  Added parameter types ">" and "P", plus opcode DCOP\_DEREF.

2017 November, A-Shell 6.5.1619:  DYNLIB now supports up to four dynamic libraries simultaneously; previously it could only handle one at a time.

2017 January, A-Shell 6.3.1542:  automatic conversion from ANSI to/from UTF8 now supported via the "A" (read only) and "a" (read/write) codes. This is used in the Linux version of the LIBXL API to handle accented and other special Latin1 characters.

2015 November, A-Shell 6.3.1500:  Routine added to A-Shell. Initially for internal use only in conjunction with LibXL, later to be documented and made available to programmers. Documentation posted January 2017.

**Subtopics**

- [DYNLIB Indirect Output](dynlibindirectouput.md)