外部関数インターフェイスを介して 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 呼び出しを行ったことがあります。また、WindowsでのCLispのUnicodeサポートが不十分であるという問題に遭遇したため、CLispでこれを機能させることもできました(CLispはUTF-16文字列を読み取るため、パスの最初の文字のみで終了しました)として)。
私が立ち往生している点は、これを機能させるために CCL にどのような機能があるかということです。正しい方向への助けをいただければ幸いです。