2

我想为我的 OCaml 应用程序制作一个 GTK 插件,使用 Dynlink 加载。如何让 ocamlbuild 在生成的插件中包含 lablgtk2 库?

作为测试,我有main.ml

let () =
  try
    Dynlink.loadfile "_build/gtk_plugin.cmxs"
  with Dynlink.Error err ->
    failwith (Dynlink.error_message err)

gtk_plugin.ml

let () =
  print_endline "GTK plugin loaded!";
  GMain.Main.main ()

_tags

<main.*>: package(dynlink)
<gtk_plugin.*>: package(lablgtk2)

但我得到:

$ ocamlbuild -use-ocamlfind main.native gtk_plugin.cmxs
$ ./main.native 
Fatal error: exception Failure("error loading shared library:
.../_build/gtk_plugin.cmxs: undefined symbol: camlGtkMain")

注意:主二进制文件不能依赖于 libgtk(可能没有安装在目标系统上) - 如果插件无法加载,我想退回到控制台模式。

4

1 回答 1

3

你需要

  1. linkall标志添加到main,否则它将删除动态插件稍后需要的 OCaml 运行时部分

  2. 使用选项编译gtk_plugin.cmxs文件-lflag lablgtk.cma(我从未通过该选项中推断出_log

ocamlbuild 推断.cmxs依赖关系的方式目前不是最佳的,而且很难,因为不同的用户可能想要不同的东西(假设存在 lib 的最小插件,或者相反可移植的静态链接的东西)。对于来自您的项目的模块,您可以编写一个foo.mldylib文件来明确说明您想要排除的内容,但我不知道是否可以包含“此外部库的所有模块”。

请注意,也可以与您的插件一起分发lablgtk.cmxs和相关.cmi的,并首先动态加载它。

mkdir lablgtk
cp `ocamlfind query lablgtk2`/lablgtk.cmxs lablgtk
cp `ocamlfind query lablgtk2`/*.cmi lablgtk
echo "\"lablgtk\": not_hygienic" >> _tags

然后在你的 main.ml

let () =
  try
    Dynlink.loadfile "lablgtk/lablgtk.cmxs";
    Dynlink.loadfile "_build/gtk_plugin.cmxs"
  ...
于 2013-11-29T22:05:48.150 回答