Allegro CL supports building shared libraries that can be used by
C/C++ programs in the same manner as they use any other function
libraries. On Windows, the library files are DLL files. This document
describes how to create such DLL's. See
unix-shared-library.htm for information on creating
similar files on UNIX machines.

Below is an example that illustrates the steps necessary to construct
and deploy an Allegro CL based DLL. The files associated with this example
are in the examples/dll/ subdirectory of the
Allegro directory.

You must have at least an Entrerprise Allegro CL license, because the
example uses generate-application (and only
Enterprise and above customers have access to that function).

Note that lnkacl.lib file (provided by Franz)
must be either in the current directory or in a directory named in the
"lib" environmental variable. It is easiest to copy it to
examples/dll/ from the Allegro directory.

You should update your PATH environment variable to include
[Allegro directory]/examples/dll/. You should
also either run Allegro CL from a DOS box/Command Prompt where the
current directory is [Allegro
directory]/examples/dll/ or you should change the current
directory in the running Lisp to [Allegro
directory]/examples/dll/ before loading
examples/dll/dist.cl. You change the directory
by evaluating:

;; Assuming the current directory is presently the Allegro directory
(chdir "examples/dll/")

A dxl file is an Allegro CL image file. It is
created by generate-application from Lisp source
files. The call to generate-application is in the file
examples/dll/dist.cl and will be described
below. Here is the examples/dll/fact.cl Lisp
source file containing code needed for fact.dxl:

The examples/dll/dist.cl file can be loaded into
Allegro CL to generate a distribution directory
examples/dll/fact/ (under the Allegro CL
installation directory) containing the fact.dxl
and associated files. Before loading
examples/dll/dist.cl, remove
examples/dll/fact/, if it exists. See
examples/dll/dist.cl contents for more
information. This file assumes you have the
generate-application functionality enabled in your Allegro
CL. Also, as noted in the file, you must first generate the
fact.dll and ftest.exe
modules as described below.

You can do this with an exported initialization function as in the
above example, or you can transparently wrap the initialization steps
within your DLL's exported functions.

Your C/C++ code must call a custom Lisp initialization function.

After calling InitializeLisp(), but before calling any of your
other Lisp code, you must call a custom initialization Lisp function
using RemoteCommand() (again, see
Section 6.0 LNKACL DLL Exported Routines). The custom
initialization function is described in steps 6 and 7 below.

Your Lisp initialization function calls this routine to fill in
addresses at runtime that your C/C++ code uses to invoke Lisp
based functionality. In the example above, the set_factorial_callback()
function provided this functionality.

Provide C/C++ wrappers for the Lisp functionality you wish to export.

The factorial() function in the above example illustrates how to do this.

You must load the lnk.fasl file into your custom Lisp image.
Ink.fasl comes from compiling the provided file
examples/dll/Ink.cl.

Remember to name the image so it matches your InitializeLisp()
argument.

If your C/C++ code process returns values, you will most likely want to
use the register-functionconvert optional argument.

The Lisp functions defined by defun-c-callable and called from
C programs should handle all Lisp errors and throws and return some
success/failure indication to the C caller (see the factorial
function for an example). Any Lisp throw past the point of call
from C is likely to produce unpredictable results.

Output to the stream bound to *initial-terminal-io* goes to the console
window. Even if InitializeLisp() is called with
make_console=0 then the console window will pop
up when output is written.

Input from the stream bound to *initial-terminal-io* will never return to the
caller. All input to this stream is sent to the initial Lisp listener
in the console window.

To allow building an application that uses a custom Lisp based DLL,
you must provide the .lib file generated when you built your DLL.

The file must reside in a directory included in the LIB environmental
variable, or it must reside in the directory where the build
occurs. Remember that you must export any functions you wish to make
available to applications using your DLL.

To allow a generated application to run, you must provide
lnkacl.dll (provided by Franz), your custom DLL, your custom
Lisp image file, and the Allegro CL license file. These files can
reside in any of the following directories:

The sys: directory as determined by the application
(that is, the result of (translate-logical-pathname
"sys:")). This will be the sys_dir argument to
InitializeLisp, or if 0, the application's working directory.
(Earlier versions of this document incorrectly said "the directory
from which the calling application loaded". That directory may not be
known and will not be searched unless it is also the directory
described in the corrected text.)

The current directory

The windows system directory

The windows directory

One of the PATH environmental variable directories

In addition, you may have to provide any DLL's required by your C/C++
compiler.

InitializeLisp

sys_dir:
directory Lisp will use as sys: for logical pathnames
(if 0, the application's working directory will be used)

make_console: if 1, open debugging console, if 0,
don't open debugging console. NOTE: this flag is only advisory. If
the application writes to the stream bound to *initial-terminal-io*
then the console window will pop up whether make_console was 0 or 1.

Return Value:
1 if found image file,
0 if couldn't find image file

See Also: TerminateLisp()

Remarks:

The image file can be a complete path or just a file name.
If just a file name, the following directories are searched, in order:

The directory from which the calling application loaded

The current directory

The windows system directory

The windows directory

The PATH environmental variable directories

The debugging console is useful during development - you can view
initialization messages, enter Lisp expressions, and manage Lisp
debugging activities.

Note that this routine returns asynchronously. The Lisp initialization
takes some time to complete. Use a subsequent synchronous
RemoteCommand() call if you desire a synchronous startup
procedure or if you wish to verify that the Lisp startup procedure has
completed successfully.

TerminateLisp()

Problem with restarting Lisp after calling TerminateLisp():
because of a design flaw, InitializeLisp() may not be called to
restart the Lisp environment after TerminateLisp() has been
called. The problem is that TerminateLisp() takes time to
actually kill the Lisp thread, but (essentially) reports that it has
succeeded too early, and the initialization routines rely on this
false report and fail when the report differs from the reality.

GetLispThread()

unsigned int GetLispThread()

Return Value:
The Lisp thread handle is returned.

Copyright (c) 1998-2009, Franz Inc. Oakland, CA., USA. All rights reserved.Documentation for Allegro CL version 8.1. This page was not revised from the 8.0 page.Created 2009.7.29.