0

感谢Jonathan Protzenko 的精彩指南,我设法在 Windows(在 Cygwin 中)上安装和运行OCaml + OPAM + utop。在utop中,我特别希望能够使用ctypes + ctypes.foreign来快速试验和原型访问各种 WinAPI 调用。从理论上讲,我成功地安装了ctypes包(成功)。不幸的是,当我尝试将它们实际加载到utop 中时,它们以令人惊讶的错误消息惨遭失败:opam install ...

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'

注意:会话的完整记录在此处— 它包含 cmd.exe 终端中的会话输出,以及Cygwin 终端utop中的附加会话的输出。rlwrap ocaml

我完全不知道为什么会发生这种情况,或者我如何进一步尝试调试/查明/诊断情况,以便我可以尝试找到一些解决方法。(顺便说一下——我是 OCaml 和 OPAM 的新手,虽然我在 C/C++ 和 Linux 方面有相当的经验。)接下来是我的一些问题,我想这些问题可能有助于解决这个问题推动我通过障碍:

  • 有没有办法在本地调整 git repo(即 ctypes)并将其传递给 OPAM 而不是原始的 github ?
  • 我设法在谷歌上搜索了一些评论,似乎提到“libffi 的静态版本”可能会起作用,正如 ctypes 问题 #198 中所暗示的那样;但我是 OCaml 的新手,不幸的是,我完全不知道如何将这个建议应用于utop
  • 我如何告诉 OPAM 哪个 libffi 用于 ctypes?(具体来说,使用“静态 libffi”?)
  • 如何检查我安装的mingw64-x86_64-libffi Cygwin 软件包是静态链接还是动态链接?或者如果提供了两种变体,那么 ctypes 使用哪一种?我在 SO 上找到了一些关于如何检测 libffi.a 是否与 PIC(?)重定位 [ -fpic?] 相关联的答案,但它们看起来都非常骇人听闻,而且我尝试过的那些似乎都没有真正起作用,至少在我的情况下.
  • 任何帮助将不胜感激。我什至不知道该问谁,因为它是 OCaml、OPAM、utop 和 Cygwin 的交叉点,所有这些都是巨大且有些不相关/正交的系统。我试过在 ctypes repo 上发布这个问题,但一个月后得到的只是一个“补丁欢迎”标签。
4

1 回答 1

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。如果在您的 PATHopam install ctypes-foreign ctypes utop中,应该开箱即用。/usr/x86_64-w64-mingw32/sys-root/mingw/bin完整的分步指南如下:

  1. 下载 64 位图形安装程序并运行它。
  2. 安装完成后,启动“Cygwin64 Terminal”(安装到开始菜单中的Cygwin组中)。
  3. 键入cygwin-install gui以启动Cygwin 设置/安装程序并使用它来安装一些文本编辑器(joenanovim或任何您喜欢的)。
  4. 使用您安装的文本编辑器编辑~/.bashrc文件,添加以下行:

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

    然后在Cygwin 终端中执行它(只需在终端中键入它,或者运行以下命令):

    $ source ~/.bashrc
    
  5. 安装depext,它将自动下载 OPAM 包所需的任何操作系统级别(本机)依赖项,使用它来安装ctypesutop

    $ opam install depext depext-cygwinports
    $ opam depext -i ctypes-foreign ctypes utop
    
  6. Cygwin 终端切换到cmd.exe例如在Cygwin 终端中键入以下命令:

    $ cmd /c start cmd
    
  7. cmd.exe终端中启动utop,并使用它来调用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

于 2016-09-22T15:35:44.733 回答