Function applied to too many arguments in lablgtk

2019-08-08 03:14发布

问题:

I need some help understanding why the following code will not compile. I am attempting to place a GSourceView2 inside a vertical box in lablgtk. I've adapted the code from this Ocaml article

open GMain
open GdkKeysyms

let locale = GtkMain.Main.init ()

let main () =
  let window = GWindow.window ~width:320 ~height:240
                              ~title:"Simple lablgtk program" () in
  let vbox = GPack.vbox ~packing:window#add () in
  window#connect#destroy ~callback:Main.quit;

  (* Sourceview *)
  let _ = new GSourceView2.source_view ~height:240 ~width:320 ~packing:vbox#add () in

  window#show ();
  Main.main ()

let () = main ()

The error I get is a bit cryptic:

Error: This function has type
         GtkSourceView2_types.source_view Gtk.obj -> GSourceView2.source_view
       It is applied to too many arguments; maybe you forgot a `;'.

However, I can instead create a GButton and set its pack argument to place it inside the vbox. The signatures for both GButton.button and GSourceView2.source_view appear to be very similar (lots of optional args followed by a unit), so I'm not quite sure what I'm missing. Any help on what I'm missing would be very helpful, as I'm still fairly new to this language.

回答1:

Since you are new to this language, I will also give you the overview of how I solved this problem so that you get a feel for the environment...unfortunately this can painful at times.

So the error you got implied the lack of a cma or cmxa (I'm not sure if you used ocamlopt or ocamlc)

Let's start by going to the source...which is available to us in either

~/.opam/archives/ or just by opam source lablgtk. We go in and see a META file, this is for ocamlfind.

after cat META we see this relevant part all the way on the bottom.

package "sourceview2" (
  exists_if = "lablgtksourceview2.cma,lablgtksourceview2.cmxa,lablgtksourceview2.cmxs"
  description = "Bindings for gtksourceview2"
  requires = "lablgtk2"
  archive(byte) = "lablgtksourceview2.cma"
  archive(native) = "lablgtksourceview2.cmxa"
)

okay, so that means that we should expect a lablgtksourceview2.cma or .cmxa to exist. We can do

cd `ocamlfind query lablgtk`

and then we can do either locate lablgtksource2.cma or find . -name lablgtksourceview2.cma. On my platform, OS X, neither existed. After some sleuthing on the lablgtk site and general googling, this was because the relevant gtk code itself was not on my machine.

for OCaml people on OS X you need to

1) opam uninstall lablgtk
(* Make sure that your path is set up correctly for PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig *)
2) brew install gtksourceview libxml2
3) opam install lablgtk lablgtk-extras

The last step might crap out. Its most likely a pkg-config path issue, Here's mine for PKG_CONFIG_PATH = /opt/X11/lib/pkgconfig/:/usr/local/Cellar/libxml2/2.9.2/lib/pkgconfig/

for OCaml people on I guess Debian based machines, this should include Ubuntu, although I'm not sure if this is the correct package name for this.

1) opam uninstall lablgtk
2) apt-get install liblablgtksourceview2-ocaml-dev
(* Not sure what the correct pkgconfig stuff is on linux but shouldn't matter I imagine *)
3) opam install lablgtk lablgtk-extras

You can do the checking for the .cma dance again after this and check with

 pwd
/Users/Edgar/.opam/4.02.1/lib/lablgtk2
~/.o/4/l/lablgtk2 ❯❯❯ ls *.cma
lablglade.cma          lablgtksourceview2.cma
lablgtk.cma            lablrsvg.cma

Yay, the relevant cma exists. We can also double check with:

ocamlfind list | grep gtk
lablgtk2            (version: 2.18.0)
lablgtk2-extras     (version: 1.5)
lablgtk2-extras.configwin (version: 1.5)
lablgtk2.auto-init  (version: n/a)
lablgtk2.glade      (version: n/a)
lablgtk2.rsvg       (version: n/a)
lablgtk2.sourceview2 (version: n/a)

and there's the relevant package, sourceview2.

Now here's your code completely self contained:

#require "lablgtk2.sourceview2"
open GMain
open GdkKeysyms

let locale = GtkMain.Main.init ()

let main () =
  let window = GWindow.window ~width:320 ~height:240
                              ~title:"Simple lablgtk program" () in
  let vbox = GPack.vbox ~packing:window#add () in
  window#connect#destroy ~callback:Main.quit;

  (* Sourceview *)
  let _ = GSourceView2.source_view ~height:240 ~width:320 ~packing:vbox#add () in

  window#show ();
  Main.main ()

let () = main ()

and I can run it successfully with utop <the_file.ml>

If you prefer to use ocamlc or ocamlopt then remove the line that starts with #require since that's just for utop, then do:

(* I just named it stackoverflow.ml, you can also use ocamlopt instead of ocamlc *)

ocamlfind ocamlc -package lablgtk2.sourceview2 -linkpkg stackoverflow.ml -o SanityCheck

Then ./SanityCheck which worked for me on OS X.



回答2:

By using new you are invoking the single-argument constructor of the class GSourceView2.source_view, not the many-argument function GSourceView2.source_view.

Although I'm not familiar with the Gtk library it seems as if the functions with the same name as the classes will return an instance of those classes, so you can probably fix your problem by simply removing the new.