我试图使用CLISP调用一些Win32函数。
我能够发出一个调用,并在Lisp中调用一个回调,但现在我不知道如何访问传递给回调的值。
其中一个值是指向struct的指针。我已经定义了这个结构,我可以打印它,得到一个#<FOREIGN-VARIABLE #x00000000>,或者把它包装在foreign-address中,然后得到#<FOREIGN-ADDRESS #x00000000> (这两者都不是真正的值或加载项),但是当我尝试对它进行deref时,我会得到以下内容:
*** - FFI:DEREF is only allowed after FFI:FOREIGN-VALUE:
(FFI:DEREF (FFI:FOREIGN-ADDRESS PRECT*))我尝试过将foreign-address调用包装在foreign-value中,尝试使用with-c-place和其他东西,但是没有任何效果。我要么没有打印任何内容(在这种情况下,假设调用过程中出现了错误并对其进行了编码),要么我得到了该错误。
我找到的唯一文档是这个dffi引用,但是它没有足够的例子,这些函数的文档也不清楚。
有人有指点吗?(双关语)我应该切换到CFFI/UFFI还是SBCL?
更新
在将指针包装在REPL中的foreign-value reload中(没有退出)之后,我让它打印了一次结构,然后它似乎在后面的reloads的回调中出错。
编辑
仍然无法让它工作;下面是代码:
(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)发布于 2014-03-10 15:30:32
使用slot和c-var-object
见slot和c-var-object。
更多的例子
中可以找到更多示例。
未来
实际上,现在sbcl比clisp维护得更好,所以您可能需要考虑切换。
https://stackoverflow.com/questions/21868843
复制相似问题