!DYNLIB.DEF [200] - DYNLIB.SBR symbols !-------------------.-------------------.-------------------.-------------------. !EDIT HISTORY ! Note: history reformatted 9-Feb-17 ! [200] 19-Oct-21 / jdm / Revisions for 64 bit (6.5.1708+ support) ! [103] 16-Jan-17 / jdm / Add DLF_ANSI_UTF8_WIDE, DLF_ASCII; revise flag values ! [102] 13-Jan-17 / jdm / Add DLF_ANSI_UTF8 ! [101] 13-Jan-17 / jdm / Support DLF_ANSI_UTF8 ! [100] 04-Jan-16 / jdm / Created !-------------------.-------------------.-------------------.-------------------. !NOTES: ! ! XCALL DYNLIB permits calling APIs implemented in DLLs (Windows) or .so's ! (shared dynamic libraries under Linux.) ! ! To use, first load the the library (at which point you need to specify the ! calling convention if it doesn't match the default for the platform.) ! ! map1 dcl, ST_DYNLIBCTL ! ... ! dcl.opcode = DCOP_LOAD ! xcall DYNLIB, dcl, libpath$ {,DLCC_C_xx {,stack size}} ! ! (this sets the dcl.handle which is used by all the other operations) ! ! Once loaded, switch to opcode DCOP_CALL and call as many functions as you ! want. The trick here is to provide both the function name and a signature ! which identifies the types and number of parameters. The signature is ! appended to the function name using the format "(???)?" where each ? ! character within the parens represents one parameter in the function, and ! one corresponding parameter in the xcall. The ? outside the parans indicates ! the type of value the function returns (v for void). In addition to constructing ! the proper signature for the API call, you also have to supply the proper ! (compatible) A-Shell parameter types to match up with the signature and the API. ! !Example: consider the GetCurrentDirectory in the Windows WIN32 API, whose ! definition looks like: ! ! DWORD WINAPI GetCurrentDirectoryA( ! _In_ DWORD nBufferLength, ! _Out_ LPTSTR lpBuffer); ! !This translates to: "GetCurrentDirectoryA(Iz)I", i.e. ! ! xcall DYNLIB, dlctl, "GetCurrentDirectoryA(Iz)I", sizeof(rootpath$), rootpath$, chcount ! ? "chcount: ";chcount ! ? "current dir: ";rootpath$ ! !The complete list of signature codes: ! 'A' : const char * (s,0) UTF8 from Latin1 (A-Shell extension) ! 'a' : char * (s,0) UTF8 from Latin1, back to Latin1 on return (A-Shell extension) ! 'B' : _Bool, bool (i,2) or i,4? ! 'c' : char (s,1) ! 'C' : unsigned char (s,1) ! 's' : short (i,2) ! 'S' : unsigned short (b,2) ! 'h' : handle (32 or 64 bit pointer, stored in X8 arg) [200] ! 'i' : int (i,4) ! 'I' : unsigned int (b,4) ! 'j' : long (i,4) ! 'J' : unsigned long (b,4) ! 'l' : long long, int64_t (?) ! 'L' : unsigned long long, uint64_t (?) ! 'f' : float (f4) ! 'd' : double (f8) ! 'p' : void* (any output vars probably need to use this) ! 'Z' : const char * (s,0) ! 'z' : char * (s,0) (A-Shell extension) ! 'W' : const wchar_t * (s) (A-Shell extension) ! 'w' : wchar_t * (s) (A-Shell extension) (A-Shell extension) ! 'U' : const wchar * (from UTF8 string) (A-Shell extension) ! 'u' : char * (from UTF8 string) (A-Shell extension) ! 'v' : void ! Examples: ! C function prototype dynlib signature ! -------------------------------------------------- ----------------- ! 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” ! struct *f5(struct *ps); "f5(h)h" ! ![103] Notes: when passing ANSI/Latin1 strings containing accented chars to ! external libraries, it is typical for Windows libraries to use wide ! characters (wchar), and for Linux libraies to use UTF8 (char*). ! Selecting the A/a or W/w options from table above will provide for ! automatic conversion from the ANSI/Latin1 typically used in A-Shell to the ! wide or UTF8 used by the library (with the reverse conversion if ! necessary on the way back). See the dynlib.def functon Fn'DynLib'StrSig$() ! to simplify selecting the right parameter signature codes based on the ! DLF_xxx flags and current platform. !-------------------------------------------------------------------------- ++ifndef DCOP_LOAD ++ifdef DYNLIB_64 ! [200] deftype DLHANDLE = x,8 ! [200] Generic 32 or 64 bit handle (use arg code h) ++else deftype DLHANDLE = b,4 ! Generic 32 bit handle ++endif ! opcodes define DCOP_LOAD = 0 define DCOP_UNLOAD = 1 define DCOP_CALL = 2 define DCOP_DEREF = 4 ! [101] dereference a ptr define DCOP_GETREF = 5 ! [101] return ptr to object ! status codes define DYNLIBE_NOERROR = 0 define DYNLIBE_VM = -1 ! bad vm or unable to create define DYNLIBE_LIB = -2 ! bad lib or unable to load define DYNLIBE_FUN = -3 ! unable to load func define DYNLIBE_PARAMS = -4 ! invalid parameter(s) define DYNLIBE_SIG = -5 ! syntax error in signature define DYNLIBE_OPCODE = -6 ! invalid opcode define DYNLIBE_SIGPAR = -7 ! mismatch between sig and param count or types define DYNLIBE_UNSUPPSIG = -8 ! unsupported type in signature define DYNLIBE_TOOMANYW = -9 ! too many w and u parameters define DYNLIBE_PLATFORM = -99 ! calling conventions define DLCC_C_DEFAULT = 0 define DLCC_C_ELLIPSIS = 100 define DLCC_C_ELLIPSIS_VARARGS = 101 define DLCC_C_X86_CDECL = 1 define DLCC_C_X86_WIN32_STD = 2 define DLCC_C_X86_WIN32_FAST_MS = 3 define DLCC_C_X86_WIN32_FAST_GNU = 4 define DLCC_C_X86_WIN32_THIS_MS = 5 define DLCC_C_X86_WIN32_THIS_GNU = 6 define DLCC_C_X64_WIN64 = 7 define DLCC_C_X64_SYSV = 8 define DLCC_C_PPC32_DARWIN = 9 define DLCC_C_PPC32_LINUX = 13 define DLCC_C_X86_PLAN9 = 19 define DLCC_C_SPARC32 = 20 define DLCC_C_SPARC64 = 21 define DLCC_SYS_DEFAULT = 200 define DLCC_SYS_X86_INT80H_LINUX = 201 define DLCC_SYS_X86_INT80H_BSD = 202 ! DYNLIBCTL flags [103] revised / expanded ---------------------------------------------- ! Error handling flags (these are used within the DYNLIB.SBR) define DLF_STATUS_BASERR = &h00000001 ! Gen. basic err (65) within XCALL on dynlib (status) errs define DLF_SYSERR_BASERR = &h00000002 ! Gen. basic err (65) within XCALL on os (syserr) errs ! Note: following flags are here for convenience, but actually need to be handled by wrapper code (not DYNLIB.SBR) define DLF_LOG_ERRORS = &h00000010 ! Write status/syserr errors to ashlog define DLF_PRINT_ERRORS = &h00000020 ! Print status/syserr errors to screen define DLF_MSGBOX_ERRORS = &h00000040 ! Report status/syserr errors via MSGBOX ! [103] String representation used by the app... define DLF_ANSI = &h00000000 ! app uses ANSI strings (128-255 assumed to be Latin1) define DLF_ASCII = &h00000100 ! app uses ASCII strings (0-127 only) define DLF_UTF8 = &h00000200 ! app uses UTF8 strings (1-5 bytes per char) define DLF_WIDE = &h00000400 ! app uses WIDE strings (2 bytes per char, aka U16) ! [103] String representation used by library ! Note that while the app representation flags are definitive, the library ! representation flags may be overridden by the library wrapper routines, based ! on platform, environment, availability, etc. For example, with the LIBXL library, ! under Windows we are only supporting the "W" functions, so it always converts to WIDE ! and uses the library's "W" functions. But under Linux it always use the "A" functions, ! and it decides whether to convert to UTF8 or just pass the strings through as is, ! based on whether DLF_ANSI or DLF_ASCII (and possibly the DLF_NO_CONVERT) is specified. ! Also note: see the functions in dynlib.bsi which use these flags to help construct ! the library routine signatures used by XCALL DYNLIB define DLF_TO_UTF8_WIDE = &h00000000 ! convert to/from UTF8 or WIDE based on lib/platform (default) define DLF_TO_WIDE = &h00001000 ! convert to/from wide define DLF_TO_UTF8 = &h00002000 ! convert to/from UTF8 define DLF_NO_CONVERT = &h00008000 ! no conversion; pass strings as-is define DLF_TO_MASK = &h0000f000 ! mask for all conversion to flags ! [103] flags indicating libary routine suffix (usually derived from above) define DLF_SUFFIX_NONE = &h00000000 ! no function name suffix define DLF_SUFFIX_A = &h00010000 ! append "A" to function names define DLF_SUFFIX_W = &h00020000 ! append "W" to function names define DLF_SUFFIX_MASK = &h000f0000 ! mask for all suffix flags ! [103] flags indicating dynlib param code to use for strings (derived from above) define DLF_STRSIG_A = &h00100000 ! ansi to/from UTF8 define DLF_STRSIG_W = &h00200000 ! ansi to/from WIDE define DLF_STRSIG_U = &h00400000 ! UTF8 to/from WIDE define DLF_STRSIG_Z = &h00800000 ! ansi to/from ansi define DLF_STRSIG_MASK = &h00f00000 ! mask for all strsig flags ! [200] old version.... !>!defstruct ST_DYNLIBCTL_OLD !>! map2 handle,DLHANDLE !>! map2 opcode,b,4 ! DCOP_xxx !>! map2 flags,b,4 ! misc option flags (see DLF_xxx) !>! map2 status,i,4 ! 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 func !>!endstruct ! [200] new version (supports 64 bit but backwards compatible) ++ifdef DYNLIB_64 ! [200] new 64 bit version defstruct ST_DYNLIBCTL map2 fill,b,4 ! [200] old handle position map2 opcode,b,4 ! DCOP_xxx map2 flags,b,4 ! misc option flags (see DLF_xxx) map2 status,i,4 ! DYNLIBE_xxx map2 syserr,i,4 ! system error set by called fun, e.g. GetLastError() for Windows; else errno map2 lastfunc$,s,56 ! [200] (was 64) function signature of last called func map2 handle,DLHANDLE ! [200] 32 or 64 bit handle endstruct ++else ! new 32 bit version defstruct ST_DYNLIBCTL map2 fill,b,4 ! [200] old handle position map2 opcode,b,4 ! DCOP_xxx map2 flags,b,4 ! misc option flags (see DLF_xxx) map2 status,i,4 ! DYNLIBE_xxx map2 syserr,i,4 ! system error set by called fun, e.g. GetLastError() for Windows; else errno map2 lastfunc$,s,56 ! [200] (was 64) function signature of last called func map2 handle,DLHANDLE ! [200] 32 or 64 bit handle map2 fill2,x,4 ! [200] endstruct ++endif ++endif