Взаимодействие с Windows API через Clozure CL
Я хочу вызвать функцию Windows API из Clozure CL через интерфейс внешних функций, но у меня возникли некоторые проблемы, потому что документации, которую я смог найти, довольно мало.
В качестве достаточно богатого примера я пытаюсь вызвать 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
(первый аргумент) черезdef-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, до некоторой степени, когда я столкнулся с проблемой плохой поддержки Unisode CLisp в Windows (у меня был только первый символ пути, потому что CLisp читает строку UTF-16 как ASCII).
Дело в том, что я застрял в том, какие функции есть в CCL, чтобы заставить эту работу. Любая помощь в правильном направлении будет высоко ценится.