On Tue, Mar 17, 2020 at 09:20:12PM +0000, Richard W.M. Jones wrote:
I assume you support pkg-config for libnbd, and thus you
should just do
#cgo pkg-config: libnbd
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include \"libnbd.h\"
+
+struct error {
+ char *error;
+ int errnum;
+};
+
+static void
+save_error (struct error *err)
+{
+ err->error = strdup (nbd_get_error ());
+ err->errnum = nbd_get_errno ();
+}
+
+static void
+free_error (struct error *err)
+{
+ free (err->error);
+}
+
+static struct nbd_handle *
+_nbd_create_wrapper (struct error *err)
+{
+ struct nbd_handle *r;
+
+ r = nbd_create ();
+ if (r == NULL)
+ save_error (err);
+ return r;
+}
+
+// There must be no blank line between end comment and import!
+//
https://github.com/golang/go/issues/9733
+*/
+import \"C\"
+
+import (
+ \"fmt\"
+ \"runtime\"
+ \"syscall\"
+)
+
+/* Handle. */
+type Libnbd struct {
+ h *C.struct_nbd_handle
+}
+
+/* Convert handle to string (just for debugging). */
+func (h *Libnbd) String () string {
+ return \"&Libnbd{}\"
+}
+
+/* All functions (except Close) return ([result,] LibnbdError). */
+type LibnbdError struct {
+ Op string // operation which failed
+ Errmsg string // string (nbd_get_error)
+ Errno syscall.Errno // errno (nbd_get_errno)
+}
+
+func (e *LibnbdError) String() string {
+ if e.Errno != 0 {
+ return fmt.Sprintf (\"%%s: %%s\", e.Op, e.Errmsg);
+ } else {
+ return fmt.Sprintf (\"%%s: %%s: %%s\", e.Op, e.Errmsg, e.Errno);
+ }
+}
+
+/* Implement the error interface */
+func (e *LibnbdError) Error() string {
+ return e.String()
+}
+
+func get_error (op string, c_err C.struct_error) *LibnbdError {
+ errmsg := C.GoString (c_err.error)
+ errno := syscall.Errno (c_err.errnum)
+ return &LibnbdError{ Op : op, Errmsg : errmsg, Errno : errno }
+}
+
+func closed_handle_error (op string) *LibnbdError {
+ return &LibnbdError{ Op : op, Errmsg : \"handle is closed\",
+ Errno : syscall.Errno (0) }
+}
+
+/* Create a new handle. */
+func Create () (*Libnbd, error) {
+ c_err := C.struct_error{}
+ c_h := C._nbd_create_wrapper (&c_err)
+ if c_h == nil {
+ err := get_error (\"create\", c_err)
+ C.free_error (&c_err)
+ return nil, err
+ }
+ h := &Libnbd{h : c_h}
+ // Finalizers aren't guaranteed to run, but try having one anyway ...
+ runtime.SetFinalizer (h, (*Libnbd).Close)
+ return h, nil
+}
+
+/* Close the handle. */
+func (h *Libnbd) Close () *LibnbdError {
+ if h.h == nil {
+ return closed_handle_error (\"close\")
+ }
+ C.nbd_close (h.h)
+ h.h = nil
+ return nil
+}
+
+";
diff --git a/generator/GoLang.mli b/generator/GoLang.mli
new file mode 100644
index 0000000..b8ec1b5
--- /dev/null
+++ b/generator/GoLang.mli
@@ -0,0 +1,19 @@
+(* nbd client library in userspace: generator
+ * Copyright (C) 2013-2020 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *)
+
+val generate_golang_libnbd_go : unit -> unit
diff --git a/generator/Makefile.am b/generator/Makefile.am
index e499ca8..0389d70 100644
--- a/generator/Makefile.am
+++ b/generator/Makefile.am
@@ -57,6 +57,8 @@ sources = \
Python.ml \
OCaml.mli \
OCaml.ml \
+ GoLang.mli \
+ GoLang.ml \
generator.ml \
$(NULL)
diff --git a/generator/generator.ml b/generator/generator.ml
index 1c97492..817c032 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -55,3 +55,6 @@ let () =
output_to "ocaml/NBD.mli" OCaml.generate_ocaml_nbd_mli;
output_to "ocaml/NBD.ml" OCaml.generate_ocaml_nbd_ml;
output_to "ocaml/nbd-c.c" OCaml.generate_ocaml_nbd_c;
+
+ output_to "golang/src/libguestfs.org/libnbd/libnbd.go"
+ GoLang.generate_golang_libnbd_go;
diff --git a/golang/Makefile.am b/golang/Makefile.am
new file mode 100644
index 0000000..47234ff
--- /dev/null
+++ b/golang/Makefile.am
@@ -0,0 +1,58 @@
+# nbd client library in userspace
+# Copyright (C) 2013-2020 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+include $(top_srcdir)/subdir-rules.mk
+
+#
http://golang.org/doc/code.html#Organization
+pkg =
libguestfs.org/libnbd
+
+source_files = \
+ src/$(pkg)/libnbd.go \
+ src/$(pkg)/libnbd_*_test.go
+
+generator_built = \
+ $(source_files)
+
+EXTRA_DIST = \
+ src/$(pkg)/.gitignore \
+ $(generator_built) \
+ config-test.go \
+ run-tests.sh
+
+if HAVE_GOLANG
+
+golangpkgdir = $(GOROOT)/pkg/$(GOOS)_$(GOARCH)/$(pkg)
+golangsrcdir = $(GOROOT)/src/pkg/$(pkg)
+
+golangpkg_DATA = \
+ pkg/$(GOOS)_$(GOARCH)/$(pkg).a
+
+pkg/$(GOOS)_$(GOARCH)/$(pkg).a: src/$(pkg)/libnbd.go
+ $(top_builddir)/run $(GOLANG) install $(pkg)
+
+golangsrc_DATA = $(source_files)
+
+TESTS_ENVIRONMENT = pkg=$(pkg) LIBNBD_DEBUG=1
+LOG_COMPILER = $(top_builddir)/run
+TESTS = run-tests.sh
+
+endif
+
+CLEANFILES += src/$(pkg)/*~
+
+clean-local:
+ rm -rf pkg
diff --git a/golang/config-test.go b/golang/config-test.go
new file mode 100644
index 0000000..e104c71
--- /dev/null
+++ b/golang/config-test.go
@@ -0,0 +1,34 @@
+/* libnbd Go configuration test
+ * Copyright (C) 2013-2020 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This is called from ./configure to check that golang works
+ * and is above the minimum required version.
+ */
+
+package main
+
+func main() {
+ /* XXX Check for minimum runtime.Version() >= "go1.1.1"
+ * Unfortunately go version numbers are not easy to parse.
+ * They have the 3 formats "goX.Y.Z", "release.rN" or
+ * "weekly.YYYY-MM-DD". The latter two formats are mostly
+ * useless, and the first one is hard to parse. See also
+ * cmpGoVersion in
+ *
http://web.archive.org/web/20130402235148/http://golang.org/src/cmd/go/ge...
+ */
I believe you can just achieve the version check using a build tag
comment at the top of the source file
eg to mandate go 1.10 or later:
// +build go1.10
See build constraints here: