|
| | | | L O A D E R
| | | | |
qdev_libloader.txt(a-pre_xxxlibs.h)
-------------------------------------
1. INTRO
=======================
One of the handiest things in the 'qdev' is the library loader. With its
help your hands are free from typing all these boring "OpenLibrary(...)"
and "CloseLibrary(...)" statements. You can request needed libraries just
by defining macros that are mostly one line long. This way you not only
give yourself more comfort, but also save on binary size because loader
will be created at compilation time with only those features you requested!
Before you go for the example usage, please take a look at the variety of
features you can embed into your prog just by using macros. First of all
macros start with '___QDEV_LIBINIT_#?' . Secondly, symbol of '<...>' means
macro really needs literal define, symbol of '[...]' means macro can be a
stub. Lastly, all the macros have no effect until you include
'a-pre_xxxlibs.h' header file. OK, so here are the features:
1. Custom library handling
###############################
___QDEV_LIBINIT_EXTBASES <...> - This macro is a container for external
bases. Like when you have just created
your own library and want it to be
loaded with this loader. Bases should
be defined one after another with a
macro below.
___QDEV_LIBINIT_ADDBASE(base, val) - The very first argument 'base'
is a full library declaration:
struct Library *mybase . The
other argument 'val' is a base
initializer and should be set
to 0 in most cases.
___QDEV_LIBINIT_EXTLIBS <...> - This macro is a container for literal
library entries. It must be specified
along with '___QDEV_LIBINIT_EXTBASES'.
Library entries must reside one next
to the other. To define them use macro
below.
___QDEV_LIBINIT_ADDLIB(n, v, b) - Arg. 'n' is a full library name
like: "mylib.library". Arg. 'v'
is the minimal library version.
And argument 'b' is a symbol of
the base: mybase .
Example:
#define ___QDEV_LIBINIT_EXTBASES \
___QDEV_LIBINIT_ADDBASE(struct Library *mybase, 0) \
___QDEV_LIBINIT_ADDBASE(struct Library *hisbase, 0)
#define ___QDEV_LIBINIT_EXTLIBS \
___QDEV_LIBINIT_ADDLIB("mylib.library", 6, mybase) \
___QDEV_LIBINIT_ADDLIB("hislib.library", 7, hisbase)
2. Built-in library handling
###############################
___QDEV_LIBINIT_<lib> <...> - Each built-in library entry requires a
minimal load version. Version can be
negative so that the library will be
treated optional. One exception to the
rule is '___QDEV_LIBINIT_SYS' where
passing negative value will cancel it
completly. See the header file for all
built-ins.
Example:
#define ___QDEV_LIBINIT_SYS 37
#define ___QDEV_LIBINIT_DOS 37
3. LibNIX stub removal
###############################
___QDEV_LIBINIT_NOEXTRAS [...] - If your intention is to code using OS
API only then define this so that the
startup code will be more crippled.
You do not need to define this when
using QCRT.
Example:
#define ___QDEV_LIBINIT_NOEXTRAS
4. Loader error reporting
###############################
___QDEV_LIBINIT_REPORTERR <...> - This macro is intended to hold a chunk
of code that is responsible for error
printout. You really want to feed it
with a macro below.
___QDEV_LIBINIT_REPORTDEF - Default error outputing code.
Currently this is 'FPrintf()'.
Example:
#define ___QDEV_LIBINIT_REPORTERR ___QDEV_LIBINIT_REPORTDEF
5. WBStartup message symbol
###############################
___QDEV_LIBINIT_DEFWBSTARTUP <...>
- Currently this is '_WBenchMsg', the
'libnix' pointer.
Example:
#define ___QDEV_LIBINIT_DEFWBSTARTUP WBenchMsg
6. Workbench process handler
###############################
___QDEV_LIBINIT_CLIONLY <...> - With this macro you tell the loader
that, whenever user launches this prog
from 'Workbench', it will be started
in a CLI - QCLI. Macro expects default
stream name. This is to be "CON:" in
most cases, but can be "NIL:" as well.
Either way this can be overriden with
global or local variable 'QCLISTREAM'
or prog. name one 'QCLISTREAM_<prog>'.
Please note that named variables have
priority over the global!
___QDEV_LIBINIT_CLIQUIET - "NIL:" stream. Total silence.
___QDEV_LIBINIT_CLISTREAM - "CON:" stream (preferred). The
window will be opened only when
some output must be done.
Example:
#define ___QDEV_LIBINIT_CLIONLY ___QDEV_LIBINIT_CLISTREAM
2. USAGE
=======================
I think it is about time for a little usage example. Following code when
compiled is safe to run both from CLI or Workbench. No, it will not use
the 'ixemul.library' and please do not specify '-noixemul' switch!
1 #define ___QDEV_LIBINIT_REPORTERR ___QDEV_LIBINIT_REPORTDEF
2 #define ___QDEV_LIBINIT_CLIONLY ___QDEV_LIBINIT_CLISTREAM
3 #define ___QDEV_LIBINIT_NOEXTRAS
4 #define ___QDEV_LIBINIT_SYS 37
5 #define ___QDEV_LIBINIT_DOS 37
6
7 #include <a-pre_xxxlibs.h>
8
9 int main(void)
10 {
11 if (pre_openlibs())
12 {
13 FPrintf(Output(), "Hellow teh world!\n");
14 }
15
16 pre_closelibs();
17
18 return 0;
19 }
gcc -nostdlib -nostartfiles -Dnostartfiles -I/gg/include/qdev \
-Wall /lib/libnix/ncrt0.o myprog.c -o myprog -L/lib/libnix -lnix
You way wonder where the hell are protos, inlines and all that? The answer
is: in the 'a-pre_xxxlibs.h' :-) . Pay attention to line 16, this statement
must always be outside any conditional!
---
megacz
| |
| | | | |
|