在Windows上的utop尝试“#require" ctypes.foreign&#34 ;;;`时出错”(Cygwin)

时间:2016-09-21 23:40:38

标签: cygwin ocaml opam libffi utop

由于awesome guide by Jonathan Protzenko,我设法在Windows(在Cygwin中)安装并运行 OCaml + OPAM + utop 。在 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'

注意:full transcript of the sessions is here - 它包含cmd.exe终端中utop会话的输出,以及Cygwin终端中的其他rlwrap ocaml会话的输出。

我完全不知道为什么会这样,或者我如何进一步尝试调试/查明/诊断情况,以便我可以尝试找到一些解决方法。 (顺便说一下 - 虽然我在C / C ++和Linux方面经验丰富,但我和OCAMl& OPAM都是新手。)以下是我所拥有的一些问题,我希望可能有所帮助轻推问题足以让我解决障碍:

  • 有没有办法在本地调整git repo(即ctypes)并将其传递给OPAM而不是原来的github?
  • 我设法谷歌some comment,这似乎提到了"a static version of libffi" might work, as hinted also in ctypes issue #198;但我是OCaml的全新手,不幸的是我不知道如何将这个建议应用于 utop
  • 如何告诉OPAM哪个libffi用于ctypes? (具体来说,使用"静态libffi"?)
  • 如何检查我安装的 mingw64-x86_64-libffi Cygwin软件包是静态链接还是动态链接?或者如果提供了两种变体,那么ctypes使用哪一种?我在SO上找到了一些关于如何检测libffi.a是否与PIC(?)重定位[-fpic?]相关联的答案,但它们看起来都非常hackish,我尝试的那些似乎都没有用,至少在我的情况下。
  • 任何帮助都将受到高度赞赏。考虑到OCaml,OPAM,utop和Cygwin的交叉,我甚至不知道该向谁提出这个问题,所有这些都是巨大的,有些不相关/正交的系统。我已经尝试了posting the issue on ctypes repo,但所有这一切都花了一个多月的时间才得到了#34; patch-welcome"标签

1 个答案:

答案 0 :(得分:1)

mingw64-x86_64-libffi附带静态和动态库,但gnu链接器默认使用动态版本。

修补ctypes的构建将非常烦人(ctypes的构建系统相当复杂,脚本和makefile的混合)。因此,请尝试以下操作:删除动态库(/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应该开箱即用。下面的完整分步指南:

  1. 下载64位graphical installer并运行它。
  2. 安装完成后,启动" Cygwin64终端" (安装到开始菜单中的 Cygwin
  3. 键入cygwin-install gui以启动 Cygwin设置/安装程序并使用它来安装一些文本编辑器( 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终端切换到 cmd.exe ,例如在 Cygwin Terminal <中键入以下命令/ EM>:

    $ cmd /c start cmd
    
  7. cmd.exe 终端中启动 utop ,然后使用它来调用MessageBox WinAPI function作为测试,确保所有人都能正常运行:

    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