title: CLISP FFI Foreign Value Issues
body: <p>I'm trying to use the CLISP FFI to call some Win32 functions.</p>
  
  <p>I was able to make a call out and have <em>that</em> call a callback in Lisp, but now I can't figure out how to access the values passed to the callback.</p>
  
  <p>One of the values is a pointer to a <code>struct</code>. I have the structure defined ok, I can print it and get a <code>#&lt;FOREIGN-VARIABLE #x00000000&gt;</code> or wrap it in <code>foreign-address</code> and get <code>#&lt;FOREIGN-ADDRESS #x00000000&gt;</code> (not the real value or addr in either), but when I try to <code>deref</code> it I get the following:</p>
  
  <pre><code>*** - FFI:DEREF is only allowed after FFI:FOREIGN-VALUE:
    (FFI:DEREF (FFI:FOREIGN-ADDRESS PRECT*))
  </code></pre>
  
  <p>I've tried to wrap the <code>foreign-address</code> call in <code>foreign-value</code>, tried to use <code>with-c-place</code>, and other things, but nothing works. I either get nothing printed (in which case I assume there was an error during the call and it borked), or I get that error.</p>
  
  <p>The only documentation I've been able to find is <a href="http://clisp.org/impnotes/dffi.html" rel="nofollow">this dffi reference</a> but it has scant examples and the documentation for those functions isn't clear.</p>
  
  <p>Anyone have any pointers? (Pun!) Should I switch to CFFI/UFFI or SBCL even?</p>
  
  <p><strong>Update</strong></p>
  
  <p>I got it to print the struct out <em>once</em> after wrapping the pointer in <code>foreign-value</code> re<code>load</code>ing it in the REPL (without exiting), then it seemed to error in the callback for subsequent re<code>load</code>s.</p>
  
  <p><strong>Edit</strong></p>
  
  <p>Still can't get it working; here's the code:</p>
  
  <pre><code>(defpackage "WIN32")
  (in-package "WIN32")
  (use-package "FFI")
  
  ; Listen for a WM_DISPLAYCHANGE message to get notifications of when
  ; a monitor (setting) is added/removed/changed
  
  
  
  (def-c-type BOOL     boolean)
  (def-c-type CHAR     char)
  (def-c-type DWORD    uint)
  (def-c-type HANDLE   c-pointer)
  (def-c-type HDC      HANDLE)
  (def-c-type HMONITOR HANDLE)
  (def-c-type HWND     HANDLE)
  (def-c-type LONG     long)
  (def-c-type LPARAM   c-pointer)
  (def-c-type LPCSTR   c-string)
  (def-c-type LPCTSTR  LPCSTR) ; LPCWSTR
  ;(def-c-type LPCWSTR  )
  (def-c-type TCHAR    CHAR) ; WCHAR
  ;(def-c-type WCHAR    )
  
  
  (defun symbol-to-keyword (sym)
    (intern (symbol-name sym) :keyword))
  
  
  (defun affix-to-symbol (prefix sym suffix)
    (intern (concatenate 'string prefix (symbol-name sym) suffix)))
  
  
  (defun car-symbol-to-keyword (pair)
    (cons
      (symbol-to-keyword (car pair))
      (cdr pair)))
  
  
  
  (defmacro def-struct-type (name &amp;rest fields)
    `(progn
      (def-c-struct ,name ,@fields)
      (def-c-type
        ,(affix-to-symbol "P" name "")
        (c-pointer ,name))
      (defconstant
        ,(affix-to-symbol "" name "-INSTANCE")
        '(c-struct ,name ,@(mapcar #'car-symbol-to-keyword fields)))
      ))
  
  
  ;typedef struct _RECT {
  ;  LONG left;
  ;  LONG top;
  ;  LONG right;
  ;  LONG bottom;
  ;} RECT, *PRECT;
  
  (def-struct-type RECT
    (left   LONG)
    (top    LONG)
    (right  LONG)
    (bottom LONG))
  
  
  ;BOOL CALLBACK MonitorEnumProc(
  ;  _In_  HMONITOR hMonitor,
  ;  _In_  HDC hdcMonitor,
  ;  _In_  LPRECT lprcMonitor,
  ;  _In_  LPARAM dwData
  ;);
  
  ;BOOL EnumDisplayMonitors(
  ;  _In_  HDC hdc,
  ;  _In_  LPCRECT lprcClip,
  ;  _In_  MONITORENUMPROC lpfnEnum,
  ;  _In_  LPARAM dwData
  ;);
  
  
  (def-call-out EnumDisplayMonitors
    (:name "EnumDisplayMonitors")
    (:library "User32.dll")
    (:arguments
      (hdc      HDC)
      (lprcClip PRECT)
      (lpfnEnum 
        (c-function
          (:arguments
            (hMonitor    HMONITOR)
            (hdcMonitor  HDC)
            (lprcMonitor PRECT)
            (dwData      LPARAM))
          (:return-type BOOL)
          (:language :stdc-stdcall)))
      (dwData   LPARAM))
    (:return-type BOOL)
    (:language :stdc-stdcall))
  (export 'EnumDisplayMonitors)
  
  
  (defun callback (hmon hdc* prect* data)
    (progn
      (format t "~A ~A ~A ~A~%" hmon hdc* (foreign-address prect*) data)
      t))
  
  (EnumDisplayMonitors nil nil #'callback nil)
  </code></pre>