我正在尝试使用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-value
中load
将其放入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)
答案 0 :(得分:0)
slot
和c-var-object
请参阅slot
和c-var-object
。
您可以在
中找到更多示例事实上,这些天sbcl比clisp更好地维护,所以你可能想考虑切换。