Ошибка при попытке `#require ctypes.foreign ;;` в utop в Windows (Cygwin)

Мне удалось установить и запустить OCaml + OPAM + utop в Windows (в Cygwin) благодаря отличное руководство Джонатана Проценко. В utop я особенно хочу иметь возможность использовать ctypes + ctypes.foreign для быстрого экспериментирования и создания прототипа доступа к различным вызовам WinAPI. Теоретически мне удалось успешно установить пакеты ctypes (opam install ... успешно). К сожалению, когда я пытаюсь загрузить их в utop, они терпят неудачу с неожиданным сообщением об ошибке:

utop # #require "ctypes.foreign";;
Error: Reference to undefined global `Ctypes_closure_properties'

Попытка сделать то же самое в rlwrap ocaml дает несколько более длинное сообщение об ошибке:

# #require "ctypes.foreign";;
C:\OCaml\lib\unix.cma: loaded
C:\OCaml\lib\bigarray.cma: loaded
C:\OCaml\lib\str.cma: loaded
C:\cygwin64\home\Mateusz\.opam\system\lib\bytes: added to search path
C:\cygwin64\home\Mateusz\.opam\system\lib\ctypes: added to search path
C:\cygwin64\home\Mateusz\.opam\system\lib\ctypes\ctypes.cma: loaded
C:\cygwin64\home\Mateusz\.opam\system\lib\ctypes\ctypes-foreign-base.cma: loaded
Cannot load required shared library dllctypes-foreign-base_stubs.
Reason: dllctypes-foreign-base_stubs.dll: Cannot resolve ffi_type_pointer.
C:\cygwin64\home\Mateusz\.opam\system\lib\ctypes\ctypes-foreign-unthreaded.cma: loaded
Characters -1--1:
  #require "ctypes.foreign";;

Error: Reference to undefined global `Ctypes_closure_properties'

Примечание. полная стенограмма сеансов находится здесь, он содержит выходные данные utop сеанса в cmd.exe, а также дополнительный rlwrap ocaml сеанс в терминале Cygwin.

Я понятия не имею, почему это происходит, или как я могу дальше попытаться отладить / определить / диагностировать ситуацию, чтобы я мог попытаться найти какое-то обходное решение. (И, кстати, я новичок в OCaml и OPAM, хотя у меня достаточно опыта работы с C / C ++ и Linux в целом.) Ниже приведены некоторые вопросы, которые, как я полагаю, могут помочь решить проблему в достаточной степени, чтобы протолкни меня через препятствие:

  • Есть ли способ настроить репозиторий git (т.е. ctypes) локально и передать его в OPAM вместо исходного github?
  • Мне удалось добавить в Google комментарий, который, кажется, упомяните, что "статическая версия libffi" может работать, что также указано в ctypes выпуск № 198; но я новичок в OCaml и, к сожалению, не имею ни малейшего представления, как применить это предложение к utop?
  • Как я могу указать OPAM, какой libffi использовать для ctypes? (в частности, чтобы использовать "static libffi"?)
  • Как я могу проверить, связан ли установленный мной пакет mingw64-x86_64-libffi Cygwin статически или динамически? или если предоставлены оба варианта, то какой из них используется ctypes? Я нашел несколько ответов на SO относительно того, как определить, связан ли libffi.a с перемещениями PIC (?) [-fpic?], Но все они казались действительно хакерскими, и ни один из тех, что я пробовал, не работал, по крайней мере, в моем кейс.
  • Любая помощь будет принята с благодарностью. Я даже не знаю, у кого спросить об этом, учитывая, что это пересечение OCaml, OPAM, utop и Cygwin, все это огромные и несколько несвязанные / ортогональные системы. Я пробовал опубликовать проблему в репозитории ctypes, но все это преодолело время месяца было ярлыком "приветствия патчей".

person akavel    schedule 21.09.2016    source источник
comment
Для локальной настройки вы можете сделать opam pin add -kgit ctypes path/to/local/repo#master   -  person Daniel Bünzli    schedule 22.09.2016
comment
Я думаю, вы могли бы настроить, какой libffi используется, используя переменные среды LIBFFI_CFLAGS и LIBFFI_LIBS. См. Этот файл github.com/ocamllabs/ocaml-ctypes / blob / master / src / discover /   -  person Daniel Bünzli    schedule 22.09.2016


Ответы (1)


mingw64-x86_64-libffi поставляется со статическими и динамическими библиотеками, но компоновщик GNU по умолчанию будет использовать динамические версии.

Исправление сборки ctypes было бы очень хлопотным делом (система сборки ctypes довольно сложна и представляет собой смесь скриптов и make-файлов). Так что просто попробуйте следующее: удалите динамические библиотеки (/usr/x86_64-w64-mingw32/sys-root/mingw/lib/libffi.dll.a и /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libffi-6.dll), перестройте ctypes, а затем восстановите удаленные файлы.

opam-репозиторий-Mingw

Кстати: https://fdopen.github.io/opam-repository-mingw/installation/ содержит исправленную версию flexdll (https://github.com/alainfrisch/flexdll/pull/3 применен - ​​проблема не специфична для libffi), который поддерживает динамические и статические версии libffi. opam install ctypes-foreign ctypes utop должен работать из коробки, если /usr/x86_64-w64-mingw32/sys-root/mingw/bin находится в вашем PATH. Полное пошаговое руководство ниже:

  1. Загрузите 64-разрядный графический установщик и запустите его.
  2. После завершения установки запустите «Cygwin64 Terminal» (устанавливается в группу Cygwin в Start Menu).
  3. Введите cygwin-install gui, чтобы запустить Cygwin Setup / Installer и использовать его для установки текстового редактора (joe или nano или vim или как хотите).
  4. С помощью установленного вами текстового редактора отредактируйте файл ~/.bashrc, добавьте следующую строку:

    export PATH="/usr/x86_64-w64-mingw32/sys-root/mingw/bin:$PATH"
    

    затем выполните его в терминале Cygwin (просто введите его в терминале или вместо этого выполните следующую команду):

    $ source ~/.bashrc
    
  5. Установите Depext, который автоматически загрузит все необходимые зависимости уровня ОС (собственные) для пакетов OPAM, и используйте его для установки ctypes и utop:

    $ opam install depext depext-cygwinports
    $ opam depext -i ctypes-foreign ctypes utop
    
  6. Переключитесь с Cygwin Terminal на cmd.exe, например, введя следующую команду в Cygwin Terminal:

    $ cmd /c start cmd
    
  7. Запустите utop в терминале cmd.exe и используйте его для вызова MessageBox Функция WinAPI в качестве проверки, что все работает хорошо:

    c:> utop
    
    utop # #require "ctypes.foreign";;
    utop # let dll = Dl.dlopen ~filename:"user32.dll" ~flags:[];;
    val dll : Dl.library = <abstr>
    utop # open Ctypes;;
    utop # let mb =
      Foreign.foreign ~from:dll "MessageBoxA"
      (ptr void @-> string @-> string @-> uint @-> returning int) ;;
    val mb : unit Ctypes_static.ptr -> bytes -> bytes -> Unsigned.uint -> int =
      <fun>
    utop # mb null "hello" "world" Unsigned.UInt.zero;;
    - : int = 1
    utop # #quit;;
    
    c:>
    

    [ПРИМЕЧАНИЕ: не все из приведенных выше команд utop могут потребоваться, но у меня это сработало.]

    utop + ctypes.foreign + WinAPI = MessageBox

person rafix    schedule 22.09.2016
comment
Вау, спасибо за ответ! Я пока не могу попробовать его, но что касается проекта opam-repository-mingw: могу ли я безопасно установить его после того, как я уже выполнил руководство protz? то есть в грязной среде cygwin ... Может быть, графический установщик создаст параллельный cygwin env? если да, то знаете ли вы, где доступны исходники графических установщиков? - person akavel; 22.09.2016
comment
Да, можно использовать графический установщик для создания отдельной установки cygwin, например C:\foo вместо C:\cygwin. Cygwin поддерживает несколько независимых установок. Вам нужно только быть осторожным с глобальными настройками среды Windows, созданными установщиком Протценко (он устанавливает $ OCAMLLIB и добавляет что-то в ваш $ PATH, что может привести к непреднамеренным побочным эффектам). новая установка cygwin (до кода, добавленного opam). Источники установщика: github.com/fdopen/opam-cygwin-installer - person rafix; 22.09.2016
comment
Удалил libffi.dll.a и libffi-6.dll, как вы предложили, затем сделал opam uninstall ctypes-foreign ctypes, затем снова opam install ..., но он все равно не работает в utop с теми же сообщениями. Что касается установщика fdopen, он не может установить conf-pkg-config, необходимый для ctypes с pkg-config: not found. Не знаю, как получить доступ к настройке cygwin здесь, чтобы попробовать установить pkg-config. [Примечание: не пытался исправить $ PATH. И $ OCAMLLIB выглядит нормально.] - person akavel; 27.09.2016
comment
Депекст / депекст-cygwinports установит для вас отсутствующие пакеты cygwin: opam install depext depext-cygwinports && opam depext -i ctypes-foreign ctypes - person rafix; 27.09.2016
comment
Woohoo, это сработало (через репозиторий fdopen и депекст), спасибо! :) Мне удалось позвонить MessageBox :) Я постараюсь отредактировать ваш ответ, чтобы добавить в него все подробности выполненных мной шагов. - person akavel; 27.09.2016