[Openmcl-devel] Win32 questions

Gary Byers gb at clozure.com
Wed Oct 15 21:18:19 PDT 2014

To digress (hopefully very briefly): lisp objects are dynamically  
typed; "foreign objects" generally aren't.  "Lisp memory" contains lisp  
objects and is managed by a lisp-aware GC; "foreign memory" doesn't  
contain lisp objects and is not generally of interest to the GC.  C  
(and other foreign code) operates on foreign objects in foreign memory  
and Lisp code operates on lisp objects in lisp memory, and the twain  
only meets in a few places (foriegn function calls and callbacks) in  
CCL.  There are a few ways of allocating and managing foreign memory  
from Lisp code in CCL and of storing and accessing foreign values in  
foreign memory; threre is (very intentionally) no way of going in the  
other direction in CCL.  Some of those ways of allocating foreign  
memory allocate it on a stack.  Hopefully, that's more than enough of a  
digression ...

Using %STACK-BLOCK (as your annotation does) is more correct, but I'd  
vote for using
RLET.  (All of these things are fairly low-level, but RLET does a  
little more for you.)

Recall that a MACPTR is a lisp object that encapsulates some absolute  
address.  WITH-MACPTRS will bind a set of variables to a set of MACPTR  
objects and declares that those variable bindings have dynamic extent  
(and therefore the MACPTRs which are the initial values of those  
variables can be stack-allocated.)  A MACPTR is a few dozem bytes at  
most, but code which allocates those small lisp objects on a lisp stack  
may CG less frequently than code that allocated them in the lisp heap.   
The original code bound SN to a NULL pointer and passed the value of  
that null pointer to the foreign fuinction; that's no different than  
the other arguments where an explicit null pointer is used.

Your annocation used (%STACK-BLOCK ((SN 32)) ...)  That will allocate  
32 bytes on a foreign stack and bind SN to a MACPTR to the address of  
that memory.  If the foreign function call returns with no error, you  
could get the value that the function stored there by something like

   (%get-unsigned-long sn  ; I'm assuming that a DWORD is a 32-bit  
unsigned integer

If you don't remember how big a DWORD is (but do remember how to  
capitalize it), you could also use RLET and PREF here.

   (rlet ((sn #>DWORD))
    (pref sn #>DWORD))

In C, you might have just said

    DWORD sn;

and that's more succinct but it's exactly what the RLET is doing.

On 10/15/2014 02:02:07 PM, Joshua Kordani wrote:
> Greetings all.  I am attempting to play with the FFI features of ccl,  
> and I've come up with this code snippet that I'd like some feedback  
> on.
> http://paste.lisp.org/display/144054
> according to the win32 api, the function that I call will return 0 on  
> error and nonzero on success.  In this case, this function is used to  
> request various bits of data about a given windows volume, and so all  
> of the arguments are optional.  arguments are set to defaults with  
> null pointers, and the ones that the user would like filled are  
> passed in pointers that I imagine are already allocated for the given  
> type of data.
> In my annotation i changed the with-mactprs macro to the %stack-block  
> macro, I guess I didn't really realize that I'm allocating foreign  
> memory, or memory that foreign code will write to that I setup is  
> considered foreign memory, and then I guess the %stack-block macro is  
> the right thing here.  Any feedback would be welcome!
> Joshua Kordani
> LSA Autonomy

------quoted attachment------
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> https://lists.clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list