CFFI和win32剪贴板访问

时间:2015-10-08 14:38:02

标签: winapi common-lisp cffi

我是Common Lisp的新手并做了一些实验。 我正努力获得对Windows剪贴板的一些访问权限,然后我找到了这个引用:

https://groups.google.com/forum/#!topic/comp.lang.lisp/hyNqn2QhUY0

这是完美的,除了它是为CLISP FFI量身定做的,我希望它与CFFI合作。  然后我尝试转换代码,并部分成功但是例程有问题  (get-clip-string),在WinXP(!)上使用Clozure CL 1.10进行测试:

测试文字:有太空服 - 将旅行

? (获得剪辑串)

  

错误:价值"有太空服 - 将旅行"不是预期的类型(UNSIGNED-BYTE 32)。   在进程监听器(1)中执行:GLOBAL-LOCK-STRING。   键入:要中止的POP,:R表示可用的重新启动列表。   类型:?其他选择。

我认为我没有在CFFI上找到类型的东西(虽然我已经阅读了手册),或CLISP上的原始处方。有人提示吗?  以下命令序列有效,但我担心这不安全:

app/helpers/application_helper.rb

(开放式剪辑0) (获取剪辑1) (close-clip 0)

这是代码:

(open-clip 0)
(get-clip 1)
(close-clip 0)

1 个答案:

答案 0 :(得分:0)

错误在您用于GetClipboardData的返回类型以及您用于GlobalLockGlobalUnlock的参数类型中。您定义GetClipboardData以返回字符串,但在C中,GetClipboardData返回HANDLE,其被定义为指向void的指针,{{1}接受的参数}和GlobalLock也是GlobalUnlock。将C函数定义更改为:

HANDLE

......问题就消失了。

如果您想使用(cffi:defcfun ("GetClipboardData" get-clip) :pointer (uformat :unsigned-int)) (cffi:defcfun ("GlobalLock" global-lock-string) :string (type :pointer)) (cffi:defcfun ("GlobalUnlock" global-unlock) :int (type :pointer)) ,还需要修复其他global-lock-*个功能以及memcpy

还有另一个错误:当您键入更正整个程序以便也可以调用set-clip-string函数时,set-clip-string似乎只能将字符串放到剪贴板上是Lisp进程的本地(我在Win7上通过SLIME使用SBCL的控制台构建)。假设您使用记事本将set-clip-string复制到剪贴板。然后试试这个:

Have Space Suit-Will Travel

所以它似乎有效。但是如果你尝试使用 Shift Ins 从剪贴板粘贴到EMACS中,你会得到:

CL-USER> (set-clip-string "MY CLIPBOARD")
1
CL-USER> (get-clip-string)
"MY CLIPBOARD"

所以真实的剪贴板仍然有记事本放在那里,你的Lisp程序只有一个私人剪贴板,不能用于将数据复制到其他程序,甚至不是EMACS会话托管它。

这种情况正在发生,因为CL-USER> Have Space Suit-Will Travel 需要在致电set-clip-string后致电empty-clip

此外,每个Windows调用都可能失败,但您的代码不会检查失败或处理错误。