5

我想通过 Clozure CL 的外部函数接口调用 Windows API 函数,但我遇到了一些问题,因为我能够找到的文档相当稀缺。

作为一个足够丰富的例子,我试图调用SHGetKnownFolderPath。它的签名是

HRESULT SHGetKnownFolderPath(const GUID &rfid, DWORD dwFlags,
                             HANDLE hToken, PWSTR *ppszPath   );

获取入口点

我可以使用以下内容来获取函数的入口点:

(open-shared-library "shell32.dll")
> #<SHLIB SHELL32.dll #x1234>
(external "SHGetKnownFolderPath")
> #<EXTERNAL-ENTRY-POINT "SHGetKnownFolderPath" (#x12345) SHELL32.dll #x123456>

获取/设置正确的方法签名

这是我认为调用它的一般步骤,但我不确定每个步骤如何:

  • 检索 CCL 为该函数生成的签名,以便我知道如何调用它。
  • 使用external-call.
  • 定义一个 FFI 结构或类来保存GUID(第一个参数)viadef-foreign-type或相关构造。
  • 调用后,使用CoTaskMemFree释放 指向的内存*ppszPath

猜测最终代码的形式

我对最终代码的一般形式的猜测是

(defun get-known-folder (guid)
   (let ((ffi-guid (allocate-ffi-memory-from-guid guid))
         (ffi-path ffi-version-of-nil)
         (path nil))
      (external-call "SHGetKnownFolderPath" ...) ;; Pass ffi-guid and ffi-path by reference.
      (setf path (convert-cstring-to-string ffi-path))
      (external-call "CoTaskMemFree" ...) ;; Free ffi-path.
      path))

在 C/FFI 和 Lisp 之间仍有各种未知函数和函数调用进行转换。

附录

我对 Windows API 非常熟悉,并且已经完成了其他语言的 Win32 API 调用。我还设法让这个在 CLisp 中工作,在某种程度上,因为我遇到了 Windows 中 CLisp 的 Unicode 支持不佳的问题(我最终只得到了路径的第一个字符,因为 CLisp 读取 UTF-16 字符串作为ASCII)。

我坚持的一点是 CCL 中有什么功能可以完成这项工作。任何在正确方向上的帮助将不胜感激。

4

0 回答 0