From: Carl Shapiro
Subject: lww foreign callable help
Date: 
Message-ID: <ouywv6u3ycg.fsf@panix3.panix.com>
The LispWorks for Windows FLI documentation describes a "foreign
callable" interface which I would like to make use of in order to call
Lisp from some random C code.  While setting up a foreign callables is
quite straight forward, I can't seem to figure out how I am supposed
to make reference to these foreign callables from C code living in a
DLL.  

There are examples in the Xanalys knowledgebas of foreign callables
being called just like any other C function, and I would like to do
similar things in my code. 

Unsurprisingly, by making reference to foreign callables in my C code
in this fashion causes all sorts of "unresolved symbol" errors when
trying to link my DLL.  Is there some sort of special declaration or
linker flag I need to use to make my DLL's compile, or Is the FLI just
not capable of doing what I think it can do?
From: Paul Tarvydas
Subject: Re: lww foreign callable help
Date: 
Message-ID: <b86T6.32011$Be4.11073222@news3.rdc1.on.home.com>
"Carl Shapiro" <········@panix.com> wrote in message
····················@panix3.panix.com...
> The LispWorks for Windows FLI documentation describes a "foreign
> callable" interface which I would like to make use of in order to call
...
> linker flag I need to use to make my DLL's compile, or Is the FLI just
> not capable of doing what I think it can do?

I went through this in detail about 3 months ago and the minutae have
already escaped my mind!

I think that this is the story:  FLI:DEFINE-FOREIGN-CALLABLE creates a
function that *can* be called from C code.

The problem is with Windows - you can't export the name of the lisp function
back to the C program at run time (you can't do this purely with C, either).
Windows expects you to use DLL's (LoadLibrary, etc) to dynamically link
named entry points.

You're getting linker errors because you're trying to do something that
Windows doesn't support.

There are two approaches:

(1) The straight-forward, knee-jerk use of define-foreign-callable applies
when you create a DLL from your lisp image.  A C program can load the lisp
DLL and call the lisp exported functions directly using the Windows DLL
protocol.

(2) If, like me, you want to live in the lisp environment, but still want to
have C-callable lisp functions, you have to use pointers to functions to
perform the "dynamic linking".  In this case, lisp loads a C DLL and stuffs
pointers in the C DLL with appropriate values.  Lisp calls C code, which in
turn, makes calls back to the foreign-callable Lisp code using the stuffed
pointers.  A simple example of this technique is documented in the LW
knowledge base #17002 ("initmyapplication" and "test").

I've succeeded in doing fairly complicated stuff with FLI (e.g. created my
own protocol for run-time loading of software components; created Windows
windows that are completely outside of CAPI with WndProcs that call lisp at
event-time), so feel free to pick my brain (or what's left of it after the
bludgeoning it received with 9 lbs. of Petzhold) if you get stuck.

NB: most of the problems I had in getting this stuff to work were to do with
the Windows calling conventions STDCALL and CDECL.  Win32 functions must be
called using STDCALL, whereas C programs, by default, think that they're
using CDECL.  STDCALL is the method that strongly-typed languages use - the
caller pushes parameters onto the stack and the callee (the called routine)
pops them.  CDECL is what C uses so that varargs can be made to work - the
caller pushes args onto the stack, calls the routine, then the caller (not
the called routine) cleans up the stack.  If you start getting random
crashes (even with code that "used to work" :-), you should immediately
suspect the calling convention and check that the FLI declaration matches
what the C compiler thinks it is doing.

Paul Tarvydas
·········@tscontrols.com