CLISP FFI外国价值问题

时间:2014-02-19 01:00:40

标签: lisp common-lisp ffi clisp

我正在尝试使用CLISP FFI调用一些Win32函数。

我能够拨打电话并让 在Lisp中调用回调,但现在我无法弄清楚如何访问传递给回调的值。

其中一个值是指向struct的指针。我将结构定义为ok,我可以打印它并获得#<FOREIGN-VARIABLE #x00000000>或将其包装在foreign-address中并获取#<FOREIGN-ADDRESS #x00000000>(不是其中的实际值或addr),但是当我尝试到deref我得到以下内容:

*** - FFI:DEREF is only allowed after FFI:FOREIGN-VALUE:
  (FFI:DEREF (FFI:FOREIGN-ADDRESS PRECT*))

我尝试将foreign-address电话打包在foreign-value中,尝试使用with-c-place等其他内容,但没有任何作用。我要么没有打印任何东西(在这种情况下我假设在通话过程中出现了错误并且它被剔除了),或者我得到了那个错误。

我能找到的唯一文件是this dffi reference,但它的例子很少,而且这些功能的文档也不清楚。

任何人都有任何指示? (双关!)我应该切换到CFFI / UFFI或SBCL吗?

更新

在将指针包裹在foreign-valueload将其放入REPL(没有退出)之后,我得到了将结构输出一次,然后它似乎出错了在后续重新load的回调中。

修改

仍然无法使其正常运作;这是代码:

(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 &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)

1 个答案:

答案 0 :(得分:0)

使用slotc-var-object

请参阅slotc-var-object

更多例子

您可以在

中找到更多示例

未来

事实上,这些天sbcl比clisp更好地维护,所以你可能想考虑切换。