OVERVIEW.............The dCLIP dynamic-linking system
HOW TO USE...........How to Add Dynamic-Linking to a Clipper Application
MEMORY POOL..........The Dynamic-Link Memory Pool
DYNAMIC LIBRARY......Creating a Dynamic-Library
LINK FUNCTIONS.......Dynamic-linking functions in DCLIPNL.LIB

OVERVIEW

The dCLIP dynamic-linking system

Description:

dCLIP uses a process referred to as "dynamic linking" to
improve the development cycle for Clipper application
programs.

Dynamic linking occurs at "run-time". All functions and
procedures that are loaded into memory through this process
will run at the same speed as functions that are linked into
the .EXE through conventional linking techniques. This
technology is also referred to as "turbo-linking" because it
allows developers to run Clipper .OBJ files without linking
to an .EXE.

The following is the method in which dCLIP allows you to
execute Clipper-compiled code without linking.

1. Any function or procedure that is called by the DO
(procedure) command or function call will be executed if
it is in memory.

2. If the function or procedure is not in memory, then dCLIP
will search all dynamic libraries which have been loaded
with the LIB (library file name) command or DC_LIBLOAD()
for the function/procedure and if it is found to exist in
a dynamic library, it will be loaded into memory from the
dynamic library file and executed. If a newer object
(.OBJ) file exists in the current directory or directory
defined with DC_SETT('ODIR'), then the .OBJ will be
loaded into memory and the function will be executed.

3. If the function/procedure is not in memory and not in a
dynamic library, then dCLIP will search all MAP files
(*.LST) which have been loaded with the MAP command or
DC_MAPLOAD() function for the function/procedure to
determine the name of the .OBJ file which contains the
function. If the .OBJ file is found to exist in the
current or DC_SETT('ODIR') directory, then the .OBJ will
be loaded into memory and the function will be executed.

4. If the function/procedure is not in memory, not in a
dynamic library and not in a MAP file, then the current
directory is searched for an .OBJ file with the name as
the function or procedure. If it is found, then the .OBJ
will be loaded into memory and the procedure will be
executed.

5. If the procedure cannot be found in memory, in a dynamic
library or in an object code file, then dCLIP will return
an "undefined function" error or "Can't find Module"
error.

"Dynamic-Linking" vs "Incremental Linking"

Clipper's dynamic-paging system for Clipper-compiled
"P-CODE" is such an effective a method of overlaying code,
that there is virtually no limit to the amount of
Clipper-compiled code that can be added to an application.
dCLIP's dynamic-linking system is not designed to improve
the memory-model of a Clipper application, but instead to
improve the development cycle of applications as they get
larger in size. Even small changes to an application can
take an extraordinary amount of time to relink if the .EXE
has to be updated to test the changes.

Patching applications via "Dynamic-linking" becomes a more
effective method than normal .EXE "incremental-linking"
systems as the application continues to grow in size. For
example, an application with a total .EXE/.OVL code of 1mb
will be "padded" with 70k of "dead space" to make room for
incremental linking when using an .EXE linker such as
Rtlink, Warplink, or Blinker. This 70k of extra memory usage
can easily cause the application to run out of memory.

Adding "dynamic-linking" to your application is as simple as
just adding 1 command to your Blinker/Rtlink link-script and
relinking your application. The minimum overhead is 18k -
25k, depending on the the linker you use for your
application.

"Automatic" Incremental-linking

The DCLIPNL.LIB library contains a function named
DC_LINKAUTO() that will compare the date and time of all
.OBJ's against the date and time of the .EXE and
automatically link the newer .OBJ's into memory at the time
the application starts. The .EXE is not affected, only the
contents of memory. This feature allows you to "patch" the
code in an .EXE without relinking the .EXE. This feature
has an obvious advantage when distributing fixes to large
applications that are being shared on a network or at remote
sites.

HOW TO USE

How to Add Dynamic-Linking to a Clipper Application

Description:

Only the DCLIPNL.LIB library and the Clipper libraries are
required to add dynamic-linking to a Clipper application.

AUTOMATIC-LINKING OF .OBJ's THAT ARE NEWER THAN .EXE

The Clipper ErrorSys() function is automatically called
during startup of all Clipper applications. DCLIPNL.LIB
library contains a version of ErrorSys() that will initialize
the dynamic-link system and load any .OBJs into memory that
are newer than the .EXE.

No changes to your source code are required. Just relink
your application using the @DCLIPNL.BL or @DCLIPNL.RT link
scripts.

CONTROLLED LINKING OF .OBJ's DURING THE RUNNING OF AN
APPLICATION

The dCLIP libraries contain a variety of IDE functions to
allow you to create your own Integrated Development
Environment for Clipper. Functions like DC_GATEWAY(),
DC_DOT(), DC_EDITPRG(), DC_COMPILE(), etc. can be used with
the dynamic-link functions like DC_OBJLOAD() and
DC_OBJRELEASE() to build an environment for making changes to
your application without quitting the application. The
DCLIP.EXE program uses all these functions and many more in a
complete ready-to-run IDE, however, the dCLIP function
libraries are designed to allow you to build your own
scaled-down or advanced development system.

A simple example of this is as follows:

PROCEDURE main
SET KEY -1 TO ide
dc_linkinit(70)
mainmenu()
return

PROCEDURE ide
local cPrgName
accept "enter program to change" to cPrgName
dc_editprg( cPrgName )
dc_compile( cPrgName )
dc_objload( cPrgName )
return

Blinker

Make sure that you include the command @DCLIPNL.BL in your
Blinker link-script before declaring any other libraries. Add
the command: BLINKER EXECUTABLE CLIPPER=X(nMemoryPool) in your
link-script to allocate the amount of memory you wish to
reserve for the dynamic-link pool. 50k-100k is recommended.
By also including the command: BLINKER ENVIRONMENT OVERRIDE
you can override the burned-in memory with the DOS command SET
CLIPPER=X(nMemoryPool).

Rtlink

Make sure that you include the command @DCLIPNL.RT in your
Rtlink link-script before declaring any other libraries. Use
the DOS command SET CLIPPER=X(nMemoryPool) before starting
your application to allocate the amount of memory you wish to
reserve for the dynamic-link pool. 50k-100k is recommended.

MEMORY POOL

The Dynamic-Link Memory Pool

Description:

The "dynamic-link pool" is an amount of memory that is reserved
for loading code from .OBJ files and/or dynamic-libraries.

The size of this pool is established by the following steps:

1. Issue a SET CLIPPER=X(nMemory) command in your Blinker
link-script or at DOS before running any Clipper application
that uses the dCLIP dynamic-link system.

2. Initialize the dynamic-link system in your application code
by calling DC_LINKINIT( (nMemory) ). The amount of
(nMemory) must be less or equal to the amount of (nMemory)
pre-allocated with SET CLIPPER in step 1 above.

If your application requires more Clipper memory free pool
(MEMORY(0)) for symbols, etc. it is recommended that you
allocate LESS linking memory with SET CLIPPER and
DC_LINKINIT(). If your application requires dynamic-linking of
large .OBJ files and performs many nested calls, then it is
recommended that you allocate MORE linking memory.

Most applications will run sufficiently well without memory
problems, provided that the individual object modules are not
too large. It is recommended that you keep object modules less
than 16k bytes in size to prevent memory fragmentation
problems.

Some applications are so large that it is impractical or
impossible to load all the object code or dynamic library lists
into memory before starting the application. The dynamic-link
system attempts to "manage" the dynamic-link pool by bringing
into memory only the functions that are called by the
application, then automatically "releasing" code from memory
that is not executing whenever more memory is needed.

This loading and unloading process can "fragment" the
dynamic-link pool so that there may be no contiguous block of
memory large enough to load a function or object. It is
therefore recommended that dynamic-linking be used as a method
to "patch" programs at runtime rather than as a means to run
complete applications.

See Also:

dc_objload()
OBJ LOAD
dc_linkinit()
SET CLIPPER

DYNAMIC LIBRARY

Creating a Dynamic-Library

Description:

Dynamic libraries (*.DLB files) are a set of object code
modules for an entire application which may be accessed by
dCLIP for integrating several applications, using a library of
user-defined functions, etc. A dynamic library is a collection
of objects that have been scanned and pre-processed for
"dynamic linking" at runtime. Objects from the dynamic library
require less "linking memory" from the object pool and less
processing time than objects loaded from .OBJ files on the
disk.

Dynamic libraries are created using the DLIB.EXE / DLIBE.EXE
utility programs supplied with dCLIP.

CREATING A DYNAMIC LIBRARY

To create a dynamic library you must first create a file with a
list of the object files which will be placed in the dynamic
library. This may be accomplished with the CAT.EXE program
supplied with dCLIP. The file with the list of object files
must have the same name as the dynamic library file which will
be created except it must have the extension .DLR.

CAT.EXE

The CAT.EXE utility is similar to the DOS DIR command. The
difference is that CAT.EXE outputs in the format (name).(ext)
and omits the date, time and length of the file. You can use
CAT.EXE to create a file consisting of a list of object
filenames that you want to include in your dynamic library.

The syntax for the CAT.EXE utility is as follows:

CAT (library name).DLR [(file spec)]

The format for (file spec) is just like the DOS DIR command and
allows you to use wildcards. The library name is the name of
the file you will be creating as an input file to be used with
the DLIB.EXE utility. This should be the same name as the name
of the dynamic library, but with the extension .DLR (dynamic
library response file).

DLIB.EXE

The syntax for creating a dynamic libary with the DLIB.EXE
utility is as follows:

DLIB (file name) [(-)]

(file name) is the name of the dynamic-library and response
file. (file name).DLR is a response file that contains a list
of object files to be added to, or deleted from a dynamic
library named (file name).DLB.

You can create (file name).DLR with the CAT.EXE utility, or
with any ASCII text editor. If a dynamic library named (file
name).DLB does not exist, it will be created.

Using the minus sign option [(-)] causes the files listed in
the (file name).DLR file to be deleted from the dynamic
library.

EXAMPLE:

To create a dynamic library for an application program titled
DBMGR.DLB, we must first include the names of all the object
modules which make up the DBMGR system in a file titled
DBMGR.DLR.

1. First, use the CAT.EXE program to create the DBMGR.DLR
file as follows:

CAT FC*.OBJ DBMGR.DLR

This becomes an input response file for use by the DLIB.EXE
utility with the name DBMGR.DLR and contents of this file
will look like this:

FCBROWSE.OBJ
FCDIR.OBJ
FCLABEL.OBJ
FCREPORT.OBJ
FCUTIL.OBJ
FC.OBJ

Note: The above file can also be created with any text
editor.

After creating the DBMGR.DLR file, we now create the dynamic
library by using the DLIB.EXE / DLIBE.EXE programs as
follows:

DLIB DBMGR

This will create a dynamic library with all the object code
from the above file list and with directory information
appended to the end of the file for searching the file at run
time. The DLIB.EXE program calls the DLIBE.EXE program which
will create a dynamic library named DBMGR.DLB.

Notes:

Caution Notes on Using Dynamic Libraries

Dynamic libraries follow the same rules during dynamic linking
that .LIB libraries follow when linking with your standard
linker. You must insure that duplicate procedure names or
function names do not exist within any of the sets of libraries
being used. You may use procedures or functions with the same
name in different libraries provided that there is no
possibility that common procedure or function names could be in
memory at the same time. This situation would occur in the
following example.

Suppose you have a dynamic library named A.DLB which contains a
module with the procedures AA and BB.

You also have a dynamic library named B.DLB which contains a
module with the procedures BB and CC.

If the application performed a call to procedure AA and
procedure CC, there is a possibility that procedure BB will be
loaded into memory from both dynamic libraries because the
entire module must be loaded and linked even if only a
procedure in the module has been called. This situation can
cause an unrecoverable error and dCLIP will return a "PTERM"
error when one of the modules is released from memory.

You are allowed however to have the same name procedure in
different dynamic libraries provided that only one procedure
may get loaded into memory. If a procedure with the same name
exists in more than one dynamic library, the first dynamic
library loaded will be the source for the desired procedure.


LINK FUNCTIONS

Dynamic-linking functions in DCLIPNL.LIB

Description:

The DCLIPNL.LIB library includes a set of functions which
provide for loading and unloading dynamic libraries and/or
object modules during the running of applications. No other
libraries (other than the Clipper libraries) are required to
add dynamic-linking to a Clipper application.

DC_LINKINIT() - Initialize the dynamic-link system.
DC_LIBLOAD() - Load a specified dynamic library (.DLB).
DC_LIBUNLD() - Unload a specified dynamic library or all
libraries.
DC_OBJLOAD() - Load a specified object module (.OBJ)
DC_OBJRELE() - Release a specified .OBJ or ALL .OBJs
from memory.
DC_MAPCREATE() - Scan .OBJ files and create a cross-reference
MAP.
DC_MAPLOAD() - Load a map for finding embedded UDF's or
procedures.
DC_MAPUNLD() - Unload previously loaded map files.
DC_LINKAUTO() - Link all .OBJ's that are newer than .EXE.


See Also:

dc_objload()
dc_conmem()
dc_objmem()
dc_libload()
dc_libunld()