[Libguestfs] [PATCH] Non-working support for GObject Introspection.

Richard W.M. Jones rjones at redhat.com
Tue Mar 16 14:42:27 UTC 2010


Read the README file at the top of this patch first.

Problems I see with GObject Introspection:

(1) Requires that your code uses GObject; obvious in hindsight given
the name.  In this case, it seems that we'd have to "register" the
guestfs_h structure with GObject (whatever that means).

(2) Cannot convert C error codes into exceptions automatically.  So
all your high level code has to check return values -- ugh.

(3) Poor type system (although at least it does have a concept of
non-nullable types).  For example, you cannot express 31 bit ints, or
range types, dependent types, constructed types, etc etc etc.

So I think it's OK if your code depends on glib, but for general C
interfaces I cannot see this catching on at the moment.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
-------------- next part --------------
>From 5842de4074aec617e6f2be41133ca4f192a3d74d Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones at redhat.com>
Date: Tue, 16 Mar 2010 14:33:23 +0000
Subject: [PATCH] Non-working support for GObject Introspection.

---
 .gitignore       |    2 +
 gir/README       |   41 +++++++++++++++++++++++++++++
 src/generator.ml |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/guestfs.h    |   22 +++++++++++++++
 src/guestfs.pod  |    6 ++++
 5 files changed, 146 insertions(+), 1 deletions(-)
 create mode 100644 gir/README

diff --git a/.gitignore b/.gitignore
index 2d7f383..5b3703a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,8 @@ fish/rc_protocol.c
 fish/rc_protocol.h
 fuse/guestmount
 fuse/guestmount.1
+gir/Guestfs-0.0.gir
+gir/Guestfs-0.0.typelib
 guestfish.1
 guestfish-actions.pod
 guestfs.3
diff --git a/gir/README b/gir/README
new file mode 100644
index 0000000..3e75f12
--- /dev/null
+++ b/gir/README
@@ -0,0 +1,41 @@
+GObject Introspection bindings
+------------------------------
+
+Although we add the necessary annotations for GObject Introspection to
+the <guestfs*.h> header files, we have not yet had satisfactory
+results using them.
+
+In theory this should allow you to call libguestfs from languages
+which we don't yet support, notably Javascript (using GJS or Seed).
+
+Here is how you can build the GIR bindings.  First you have to build
+libguestfs normally, then:
+
+  cd gir
+  g-ir-scanner -n Guestfs --nsversion 0.0 \
+    -L ../src/.libs -lguestfs \
+    ../src/guestfs.h > Guestfs-0.0.gir
+  g-ir-compiler Guestfs-0.0.gir > Guestfs-0.0.typelib
+
+If that went OK, then copy 'Guestfs-0.0.typelib' into the public
+directory '/usr/lib{,64}/girepository-1.0/' (or you can make a symlink
+which works just as well).
+
+In theory you should be able to use this immediately from gjs-console:
+
+  LIBGUESTFS_DEBUG=1 gjs-console
+  gjs> const Guestfs = imports.gi.Guestfs;
+  gjs> g = Guestfs.create ();
+
+Currently this gives the following error:
+
+  new guestfs handle 0x2537d00
+  Error: No exception was set, but object construction failed somehow
+
+Because the 'new guestfs handle 0x..' debug message was printed, we
+know in fact that construction succeeded!
+
+It seems we need to "register" the guestfs_h handle with GObject.  I
+can't get any straight answer to how that would be done.
+
+ - RWMJ 2010-03-16.
diff --git a/src/generator.ml b/src/generator.ml
index 486b9d8..8b463d3 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -5318,8 +5318,82 @@ and generate_actions_h () =
   List.iter (
     fun (shortname, style, _, _, _, _, _) ->
       let name = "guestfs_" ^ shortname in
+
+      (* GObject Introspection header.  Still very much experimental. *)
+      pr "/**\n";
+      pr " * %s:\n" name;
+      pr " *\n";
+      pr " * @handle: (in): The guestfs handle.\n";
+      List.iter (
+        function
+        | String n ->
+            pr " * @%s: (transfer none): A string.\n" n
+        | Device n ->
+            pr " * @%s: (transfer none): Device name.\n" n
+        | Pathname n ->
+            pr " * @%s: (transfer none): Path.\n" n
+        | Dev_or_Path n ->
+            pr " * @%s: (transfer none): Device name or path.\n" n
+        | OptString n ->
+            pr " * @%s: (transfer none) (allow-none): A string.\n" n
+        | StringList n ->
+            pr " * @%s: (transfer none) (array zero-terminated=1): A list of strings.\n" n
+        | DeviceList n ->
+            pr " * @%s: (transfer none) (array zero-terminated=1): A list of device names.\n" n
+        | Bool  n ->
+            pr " * @%s: (type boolean): A boolean.\n" n
+        | Int n ->
+            pr " * @%s: A small integer.\n" n
+        | Int64  n ->
+            pr " * @%s: A 64 bit integer.\n" n
+        | FileIn n ->
+            pr " * @%s: (transfer none): Source file to upload from.\n" n
+        | FileOut n ->
+            pr " * @%s: (transfer none): Destination file to download to.  If this file exists, it is overwritten.\n" n
+      ) (snd style);
+      (match fst style with
+       | RBufferOut _ ->
+           pr " * @size_r: (out): Size of returned buffer.\n"
+       | _ -> ()
+      );
+      pr " *\n";
+      pr " * Returns: ";
+      (match fst style with
+       | RErr ->
+           pr "0 on success or -1 on error.\n"
+       | RInt n ->
+           pr "%s >= 0 on success or -1 on error.\n" n
+       | RInt64 n ->
+           pr "%s on success or -1 on error.\n" n
+       | RBool n ->
+           pr "boolean value %s on success or -1 on error.\n" n
+       | RConstString n ->
+           pr "(transfer none) (allow none): %s on success or NULL on error.\n" n
+       | RConstOptString n ->
+           pr "(transfer none) (allow none): %s.\n" n
+       | RString n ->
+           pr "(transfer full) (allow none): %s on success or NULL on error.\n" n
+       | RStringList n ->
+           pr "(transfer full) (allow none): %s on success or NULL on error.\n" n
+       | RStruct (n, sn) ->
+           pr "(transfer full) (allow none): %s on success or NULL on error.\n" n;
+           pr " *\n";
+           pr " * Free-function: guestfs_%s\n" sn
+       | RStructList (n, sn) ->
+           pr "(transfer full) (allow none): %s on success or NULL on error.\n" n;
+           pr " *\n";
+           pr " * Free-function: guestfs_%s_list\n" sn
+       | RHashtable n ->
+           pr "(transfer full) (allow none): %s as (key, value) pairs on success or NULL on error.\n" n
+       | RBufferOut n ->
+           pr "(transfer full) (allow none) (array fixed-size=size_r): %s on success or NULL on error.\n" n
+      );
+      pr " */\n";
+
       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
-        name style
+        name style;
+
+      pr "\n";
   ) all_functions
 
 (* Generate the guestfs-internal-actions.h file. *)
diff --git a/src/guestfs.h b/src/guestfs.h
index 5b8ad09..4bd81b4 100644
--- a/src/guestfs.h
+++ b/src/guestfs.h
@@ -37,10 +37,32 @@ extern "C" {
 typedef struct guestfs_h guestfs_h;
 
 /*--- Connection management ---*/
+
+/**
+ * guestfs_create:
+ *
+ * Returns: (transfer full): Return the newly created guestfs handle.
+ *
+ * Free-function: guestfs_close
+ */
 extern guestfs_h *guestfs_create (void);
+
+/**
+ * guestfs_close:
+ *
+ * @g: (in) (transfer full): The guestfs handle.
+ */
 extern void guestfs_close (guestfs_h *g);
 
 /*--- Error handling ---*/
+
+/**
+ * guestfs_last_error:
+ *
+ * @g: (in): The guestfs handle.
+ *
+ * Returns: (transfer none): The last error on this handle.
+ */
 extern const char *guestfs_last_error (guestfs_h *g);
 
 typedef void (*guestfs_error_handler_cb) (guestfs_h *g, void *data, const char *msg);
diff --git a/src/guestfs.pod b/src/guestfs.pod
index d005257..48a9d5f 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -493,6 +493,12 @@ This is the only language binding that working but incomplete.  Only
 calls which return simple integers have been bound in Haskell, and we
 are looking for help to complete this binding.
 
+=item B<GObject Introspection>
+
+We have some half-working support for GIR.  See C<gir/README> in the
+source.  If it worked, GIR support would allow you to call libguestfs
+from many languages, in particular Javascript.
+
 =item B<Java>
 
 Full documentation is contained in the Javadoc which is distributed
-- 
1.6.5.2



More information about the Libguestfs mailing list