Richard W.M. Jones
2020-Mar-17 21:20 UTC
[Libguestfs] [PATCH libnbd v2 0/3] Unfinished golang bindings.
These bindings get as far as running very simple connections. However there are many missing parts still: * No callbacks. * No functions which handle buffers (pread/pwrite!) This is posted just for general early interest, not even for review. Rich.
Richard W.M. Jones
2020-Mar-17 21:20 UTC
[Libguestfs] [PATCH libnbd v2 1/3] generator: Modify C.print_* with optional parens flag.
Controls whether or not we print the parentheses around the function
parameters.
---
generator/C.ml | 26 ++++++++++++++------------
generator/C.mli | 5 +++--
2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/generator/C.ml b/generator/C.ml
index e79ac42..568e3f1 100644
--- a/generator/C.ml
+++ b/generator/C.ml
@@ -96,16 +96,17 @@ let rec name_of_arg = function
| UInt32 n -> [n]
| UInt64 n -> [n]
-let rec print_arg_list ?(wrap = false) ?maxcol ?handle ?types args optargs -
pr "(";
+let rec print_arg_list ?(wrap = false) ?maxcol ?handle ?types ?(parens = true)
+ args optargs + if parens then pr "(";
if wrap then
pr_wrap ?maxcol ','
- (fun () -> print_arg_list_no_parens ?handle ?types args optargs)
+ (fun () -> print_arg_list' ?handle ?types args optargs)
else
- print_arg_list_no_parens ?handle ?types args optargs;
- pr ")"
+ print_arg_list' ?handle ?types args optargs;
+ if parens then pr ")"
-and print_arg_list_no_parens ?(handle = false) ?(types = true) args optargs
+and print_arg_list' ?(handle = false) ?(types = true) args optargs let
comma = ref false in
if handle then (
comma := true;
@@ -191,16 +192,17 @@ let print_extern ?wrap name args optargs ret print_call
?wrap name args optargs ret;
pr ";\n"
-let rec print_cbarg_list ?(wrap = false) ?maxcol ?types cbargs - pr
"(";
+let rec print_cbarg_list ?(wrap = false) ?maxcol ?types ?(parens = true)
+ cbargs + if parens then pr "(";
if wrap then
pr_wrap ?maxcol ','
- (fun () -> print_cbarg_list_no_parens ?types cbargs)
+ (fun () -> print_cbarg_list' ?types cbargs)
else
- print_cbarg_list_no_parens ?types cbargs;
- pr ")"
+ print_cbarg_list' ?types cbargs;
+ if parens then pr ")"
-and print_cbarg_list_no_parens ?(types = true) cbargs +and
print_cbarg_list' ?(types = true) cbargs if types then pr "void
*";
pr "user_data";
diff --git a/generator/C.mli b/generator/C.mli
index 7748bc7..c8268c1 100644
--- a/generator/C.mli
+++ b/generator/C.mli
@@ -25,9 +25,10 @@ val generate_docs_api_links_pod : unit -> unit
val generate_docs_api_flag_links_pod : unit -> unit
val generate_docs_nbd_pod : string -> API.call -> unit -> unit
val print_arg_list : ?wrap:bool -> ?maxcol:int ->
- ?handle:bool -> ?types:bool ->
+ ?handle:bool -> ?types:bool -> ?parens:bool ->
API.arg list -> API.optarg list -> unit
-val print_cbarg_list : ?wrap:bool -> ?maxcol:int -> ?types:bool ->
+val print_cbarg_list : ?wrap:bool -> ?maxcol:int ->
+ ?types:bool -> ?parens:bool ->
API.cbarg list -> unit
val errcode_of_ret : API.ret -> string option
val type_of_ret : API.ret -> string
--
2.25.0
Richard W.M. Jones
2020-Mar-17 21:20 UTC
[Libguestfs] [PATCH libnbd v2 2/3] Add outline framework for Go language bindings (golang).
This simply compiles, passes tests, but is only able open a handle.
This commit does not contain the full bindings.
---
Makefile.am | 2 +
configure.ac | 32 ++++
generator/GoLang.ml | 150 ++++++++++++++++++
generator/GoLang.mli | 19 +++
generator/Makefile.am | 2 +
generator/generator.ml | 3 +
golang/Makefile.am | 58 +++++++
golang/config-test.go | 34 ++++
golang/examples/LICENSE-FOR-EXAMPLES | 38 +++++
golang/examples/Makefile.am | 21 +++
golang/run-tests.sh | 24 +++
golang/src/libguestfs.org/libnbd/.gitignore | 1 +
.../libnbd/libnbd_010_load_test.go | 25 +++
.../libnbd/libnbd_100_handle_test.go | 29 ++++
run.in | 17 ++
15 files changed, 455 insertions(+)
diff --git a/Makefile.am b/Makefile.am
index bf2db68..a9f13ca 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,6 +43,8 @@ SUBDIRS = \
ocaml \
ocaml/examples \
ocaml/tests \
+ golang \
+ golang/examples \
interop \
fuzzing \
bash \
diff --git a/configure.ac b/configure.ac
index 9fd284b..36617fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -403,6 +403,34 @@ AS_IF([test "x$enable_python" !=
"xno"],[
AM_CONDITIONAL([HAVE_PYTHON],
[test "x$PYTHON" != "xno" && test
"x$have_python_module" = "x1" ])
+dnl Golang.
+AC_ARG_ENABLE([golang],
+ AS_HELP_STRING([--disable-golang], [disable Go language bindings]),
+ [],
+ [enable_golang=yes])
+AS_IF([test "x$enable_golang" != "xno"],[
+ AC_CHECK_PROG([GOLANG],[go],[go],[no])
+ AS_IF([test "x$GOLANG" != "xno"],[
+ AC_MSG_CHECKING([if $GOLANG is usable])
+ AS_IF([$GOLANG run $srcdir/golang/config-test.go
2>&AS_MESSAGE_LOG_FD],[
+ AC_MSG_RESULT([yes])
+
+ # Substitute some golang environment.
+ GOOS=`$GOLANG env GOOS`
+ GOARCH=`$GOLANG env GOARCH`
+ GOROOT=`$GOLANG env GOROOT`
+ AC_SUBST([GOOS])
+ AC_SUBST([GOARCH])
+ AC_SUBST([GOROOT])
+ ],[
+ AC_MSG_RESULT([no])
+ AC_MSG_WARN([golang ($GOLANG) is installed but not usable])
+ GOLANG=no
+ ])
+ ])
+],[GOLANG=no])
+AM_CONDITIONAL([HAVE_GOLANG],[test "x$GOLANG" != "xno"])
+
dnl Produce output files.
AC_CONFIG_HEADERS([config.h])
@@ -423,6 +451,8 @@ AC_CONFIG_FILES([Makefile
fuse/Makefile
fuzzing/Makefile
generator/Makefile
+ golang/Makefile
+ golang/examples/Makefile
include/Makefile
interop/Makefile
lib/Makefile
@@ -472,6 +502,8 @@ feature "Bash tab completion ....................
" \
echo
echo "Language bindings:"
echo
+feature "Go ..................................... " \
+ test "x$HAVE_GOLANG_TRUE" = "x"
feature "OCaml .................................. " \
test "x$HAVE_OCAML_TRUE" = "x"
feature "Python ................................. " \
diff --git a/generator/GoLang.ml b/generator/GoLang.ml
new file mode 100644
index 0000000..1b8f20b
--- /dev/null
+++ b/generator/GoLang.ml
@@ -0,0 +1,150 @@
+(* 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
+ *)
+
+(* Go language bindings. *)
+
+open Printf
+
+open API
+open Utils
+
+let generate_golang_libnbd_go () + generate_header CStyle;
+
+ pr "\
+package libnbd
+
+/*
+#cgo CFLAGS:
+#cgo LDFLAGS: -lnbd
+
+#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/get.go?m=text
+ */
+}
diff --git a/golang/examples/LICENSE-FOR-EXAMPLES
b/golang/examples/LICENSE-FOR-EXAMPLES
new file mode 100644
index 0000000..4986466
--- /dev/null
+++ b/golang/examples/LICENSE-FOR-EXAMPLES
@@ -0,0 +1,38 @@
+The files in the golang/examples/ directory are licensed under this
+very permissive BSD license. This means that you can copy, use, adapt
+and modify them without any significant restrictions. You can also
+combine them with proprietary code or include them in code that is
+distributed under other open source licenses.
+
+----------------------------------------------------------------------
+
+libnbd examples
+Copyright (C) 2013-2020 Red Hat Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+* Neither the name of Red Hat nor the names of its contributors may be
+used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS''
AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/golang/examples/Makefile.am b/golang/examples/Makefile.am
new file mode 100644
index 0000000..90498ab
--- /dev/null
+++ b/golang/examples/Makefile.am
@@ -0,0 +1,21 @@
+# 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
+
+EXTRA_DIST = \
+ LICENSE-FOR-EXAMPLES
diff --git a/golang/run-tests.sh b/golang/run-tests.sh
new file mode 100755
index 0000000..a155819
--- /dev/null
+++ b/golang/run-tests.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -
+# 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
+
+set -e
+
+# The -count=1 parameter is the "idiomatic way to bypass test
caching".
+# https://golang.org/doc/go1.10#test
+# The -v option enables verbose output.
+$GOLANG test -count=1 -v $pkg
diff --git a/golang/src/libguestfs.org/libnbd/.gitignore
b/golang/src/libguestfs.org/libnbd/.gitignore
new file mode 100644
index 0000000..a2ce7eb
--- /dev/null
+++ b/golang/src/libguestfs.org/libnbd/.gitignore
@@ -0,0 +1 @@
+/libnbd.go
diff --git a/golang/src/libguestfs.org/libnbd/libnbd_010_load_test.go
b/golang/src/libguestfs.org/libnbd/libnbd_010_load_test.go
new file mode 100644
index 0000000..24cfe66
--- /dev/null
+++ b/golang/src/libguestfs.org/libnbd/libnbd_010_load_test.go
@@ -0,0 +1,25 @@
+/* libnbd golang tests
+ * 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.
+ */
+
+package libnbd
+
+import "testing"
+
+func Test010Load (t *testing.T) {
+ /* Nothing - just test that the library can be linked to. */
+}
diff --git a/golang/src/libguestfs.org/libnbd/libnbd_100_handle_test.go
b/golang/src/libguestfs.org/libnbd/libnbd_100_handle_test.go
new file mode 100644
index 0000000..a3d933d
--- /dev/null
+++ b/golang/src/libguestfs.org/libnbd/libnbd_100_handle_test.go
@@ -0,0 +1,29 @@
+/* libnbd golang tests
+ * 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.
+ */
+
+package libnbd
+
+import "testing"
+
+func Test100Handle (t *testing.T) {
+ h, err := Create ()
+ if err != nil {
+ t.Errorf ("could not create handle: %s", err)
+ }
+ h.Close ()
+}
diff --git a/run.in b/run.in
index 0411c85..9ffece5 100755
--- a/run.in
+++ b/run.in
@@ -78,6 +78,23 @@ export PYTHONPATH
prepend CAML_LD_LIBRARY_PATH "$b/ocaml"
export CAML_LD_LIBRARY_PATH
+# For golang.
+export GOLANG="@GOLANG@"
+prepend GOPATH "$b/golang"
+export GOPATH
+if [ -z "$CGO_CFLAGS" ]; then
+ CGO_CFLAGS="-I$s/include -I$b"
+else
+ CGO_CFLAGS="$CGO_CFLAGS -I$s/include -I$b"
+fi
+export CGO_CFLAGS
+if [ -z "$CGO_LDFLAGS" ]; then
+ CGO_LDFLAGS="-L$b/lib/.libs"
+else
+ CGO_LDFLAGS="$CGO_LDFLAGS -L$b/lib/.libs"
+fi
+export CGO_LDFLAGS
+
# This is a cheap way to find some use-after-free and uninitialized
# read problems when using glibc.
export MALLOC_CHECK_=1
--
2.25.0
Richard W.M. Jones
2020-Mar-17 21:20 UTC
[Libguestfs] [PATCH libnbd v2 3/3] golang: Add straightforward bindings, without callbacks.
---
generator/GoLang.ml | 336 +++++++++++++++++-
.../libnbd/libnbd_200_connect_command_test.go | 35 ++
2 files changed, 367 insertions(+), 4 deletions(-)
diff --git a/generator/GoLang.ml b/generator/GoLang.ml
index 1b8f20b..e5fb97c 100644
--- a/generator/GoLang.ml
+++ b/generator/GoLang.ml
@@ -23,6 +23,304 @@ open Printf
open API
open Utils
+let go_name_of_arg = function
+ | Bool n -> n
+ | BytesIn (n, len) -> n
+ | BytesOut (n, len) -> n
+ | BytesPersistIn (n, len) -> n
+ | BytesPersistOut (n, len) -> n
+ | Closure { cbname } -> cbname
+ | Enum (n, _) -> n
+ | Fd n -> n
+ | Flags (n, _) -> n
+ | Int n -> n
+ | Int64 n -> n
+ | Path n -> n
+ | SockAddrAndLen (n, len) -> n
+ | String n -> n
+ | StringList n -> n
+ | UInt n -> n
+ | UInt32 n -> n
+ | UInt64 n -> n
+
+let go_arg_type_to_string = function
+ | Bool _ -> "bool"
+ | BytesIn _ -> "*string/*XXX*/"
+ | BytesPersistIn _ -> "*string/*XXX*/"
+ | BytesOut _ -> "*string/*XXX*/"
+ | BytesPersistOut _ -> "*string/*XXX*/"
+ | Closure { cbargs } -> "func (/*XXX*/)"
+ | Enum _ -> "uint32"
+ | Fd _ -> "int/*XXX*/"
+ | Flags _ -> "uint32"
+ | Int _ -> "int"
+ | Int64 _ -> "int64"
+ | Path _ -> "string"
+ | SockAddrAndLen _ -> "string"
+ | String _ -> "string"
+ | StringList _ -> "[]string"
+ | UInt _ -> "uint"
+ | UInt32 _ -> "uint32"
+ | UInt64 _ -> "uint64"
+
+let go_name_of_optarg = function
+ | OClosure { cbname } -> String.capitalize_ascii cbname
+ | OFlags (n, _) -> String.capitalize_ascii n
+
+(* For consistency every method will return (type, error) where
+ * type is defined by this function. However some functions
+ * never really have a type (RErr) and others never really have
+ * an error (RUInt).
+ *)
+let go_ret_type = function
+ | RBool -> "bool"
+ | RStaticString -> "*string"
+ | RErr -> "int" (* always 0 *)
+ | RFd -> "int/*XXX*/"
+ | RInt -> "int"
+ | RInt64 -> "int64"
+ | RCookie -> "int64"
+ | RString -> "*string"
+ | RUInt -> "uint"
+
+let go_ret_error = function
+ | RBool -> "false"
+ | RStaticString -> "nil"
+ | RErr -> "0"
+ | RFd -> "0/*XXX*/"
+ | RInt -> "0"
+ | RInt64 -> "0"
+ | RCookie -> "0"
+ | RString -> "nil"
+ | RUInt -> "0"
+
+let go_ret_c_errcode = function
+ | RBool -> Some "-1"
+ | RStaticString -> Some "nil"
+ | RErr -> Some "-1"
+ | RFd -> Some "-1/*XXX*/"
+ | RInt -> Some "-1"
+ | RInt64 -> Some "-1"
+ | RCookie -> Some "-1"
+ | RString -> Some "nil"
+ | RUInt -> None
+
+(* We need a wrapper around every function (except Close) to
+ * handle errors because cgo calls are sequence points and
+ * could result in us being rescheduled on another thread,
+ * but libnbd error handling means we must call nbd_get_error
+ * etc from the same thread.
+ *)
+let print_wrapper (name, { args; optargs; ret }) + let ret_c_type =
C.type_of_ret ret and errcode = C.errcode_of_ret ret in
+ pr "static %s\n" ret_c_type;
+ pr "_nbd_%s_wrapper (struct error *err,\n" name;
+ pr " ";
+ C.print_arg_list ~wrap:true ~handle:true ~parens:false args optargs;
+ pr ")\n";
+ pr "{\n";
+ pr " %s ret;\n" ret_c_type;
+ pr "\n";
+ pr " ret = nbd_%s " name;
+ C.print_arg_list ~wrap:true ~handle:true ~types:false args optargs;
+ pr ";\n";
+ (match errcode with
+ | None -> ()
+ | Some errcode ->
+ pr " if (ret == %s)\n" errcode;
+ pr " save_error (err);\n";
+ );
+ pr " return ret;\n";
+ pr "}\n";
+ pr "\n"
+
+let print_binding (name, { args; optargs; ret; shortdesc }) + let uname =
String.capitalize_ascii name in
+
+ (* Tedious method of passing optional arguments in golang. *)
+ if optargs <> [] then (
+ pr "/* Struct carrying optional arguments for %s. */\n" uname;
+ pr "type Optargs_%s struct {\n" uname;
+ List.iter (
+ fun optarg ->
+ let fname = go_name_of_optarg optarg in
+ pr " /* %s field is ignored unless %s_is_set == true. */\n"
+ fname fname;
+ pr " %s_is_set bool\n" fname;
+ pr " %s " fname;
+ (match optarg with
+ | OClosure { cbargs } -> pr "func (/*XXX*/)"
+ | OFlags _ -> pr "uint32"
+ );
+ pr "\n"
+ ) optargs;
+ pr "}\n";
+ pr "\n";
+ );
+
+ (* Define the golang function which calls the C wrapper. *)
+ pr "/* %s: %s */\n" uname shortdesc;
+ pr "func (h *Libnbd) %s (" uname;
+ let comma = ref false in
+ List.iter (
+ fun arg ->
+ if !comma then pr ", ";
+ comma := true;
+ pr "%s %s" (go_name_of_arg arg) (go_arg_type_to_string arg)
+ ) args;
+ if optargs <> [] then (
+ if !comma then pr ", ";
+ comma := true;
+ pr "optargs *Optargs_%s" uname
+ );
+ pr ") (%s, error)" (go_ret_type ret);
+ pr " {\n";
+ pr " if h.h == nil {\n";
+ pr " return %s, closed_handle_error (\"%s\")\n"
+ (go_ret_error ret) name;
+ pr " }\n";
+ pr "\n";
+ pr " c_err := C.struct_error{}\n";
+ List.iter (
+ function
+ | Bool n ->
+ pr " c_%s := C.bool (%s)\n" n n
+ | BytesIn (n, len) ->
+ pr " var c_%s unsafe.Pointer /* XXX */\n" n;
+ pr " var c_%s C.size_t /* XXX */\n" len;
+ | BytesOut (n, len) ->
+ pr " var c_%s unsafe.Pointer /* XXX */\n" n;
+ pr " var c_%s C.size_t /* XXX */\n" len;
+ | BytesPersistIn (n, len) ->
+ pr " var c_%s unsafe.Pointer /* XXX */\n" n;
+ pr " var c_%s C.size_t /* XXX */\n" len;
+ | BytesPersistOut (n, len) ->
+ pr " var c_%s unsafe.Pointer /* XXX */\n" n;
+ pr " var c_%s C.size_t /* XXX */\n" len;
+ | Closure { cbname } ->
+ pr " c_%s := C.nbd_%s_callback{} /* XXX */\n" cbname cbname
+ | Enum (n, _) ->
+ pr " c_%s := C.int (%s)\n" n n
+ | Fd n ->
+ pr " c_%s := C.int (%s) /* XXX */\n" n n
+ | Flags (n, _) ->
+ pr " c_%s := C.uint32_t (%s)\n" n n
+ | Int n ->
+ pr " c_%s := C.int (%s)\n" n n
+ | Int64 n ->
+ pr " c_%s := C.int64_t (%s)\n" n n
+ | Path n ->
+ pr " c_%s := C.CString (%s)\n" n n;
+ pr " defer C.free (unsafe.Pointer (c_%s))\n" n
+ | SockAddrAndLen (n, len) ->
+ pr " panic (\"SockAddrAndLen not supported\")\n";
+ pr " var c_%s *C.struct_sockaddr\n" n;
+ pr " var c_%s C.uint\n" len
+ | String n ->
+ pr " c_%s := C.CString (%s)\n" n n;
+ pr " defer C.free (unsafe.Pointer (c_%s))\n" n
+ | StringList n ->
+ pr " c_%s := arg_string_list (%s)\n" n n;
+ pr " defer free_string_list (c_%s)\n" n
+ | UInt n ->
+ pr " c_%s := C.uint (%s)\n" n n
+ | UInt32 n ->
+ pr " c_%s := C.uint32_t (%s)\n" n n
+ | UInt64 n ->
+ pr " c_%s := C.uint64_t (%s)\n" n n
+ ) args;
+ if optargs <> [] then (
+ List.iter (
+ function
+ | OClosure { cbname } ->
+ pr " c_%s := C.nbd_%s_callback{} /* XXX */\n" cbname
cbname
+ | OFlags (n, _) ->
+ pr " var c_%s C.uint32_t\n" n
+ ) optargs;
+ pr " if optargs != nil {\n";
+ List.iter (
+ fun optarg ->
+ pr " if optargs.%s_is_set {\n" (go_name_of_optarg
optarg);
+ (match optarg with
+ | OClosure { cbname } -> () (* XXX *)
+ | OFlags (n, _) ->
+ pr " c_%s = C.uint32_t (optargs.%s)\n"
+ n (go_name_of_optarg optarg);
+ );
+ pr " }\n";
+ ) optargs;
+ pr " }\n";
+ );
+ pr "\n";
+ pr " ret := C._nbd_%s_wrapper (&c_err, h.h" name;
+ List.iter (
+ function
+ | Bool n -> pr ", c_%s" n
+ | BytesIn (n, len) -> pr ", c_%s, c_%s" n len
+ | BytesOut (n, len) -> pr ", c_%s, c_%s" n len
+ | BytesPersistIn (n, len) -> pr ", c_%s, c_%s" n len
+ | BytesPersistOut (n, len) -> pr ", c_%s, c_%s" n len
+ | Closure { cbname } -> pr ", c_%s" cbname
+ | Enum (n, _) -> pr ", c_%s" n
+ | Fd n -> pr ", c_%s" n
+ | Flags (n, _) -> pr ", c_%s" n
+ | Int n -> pr ", c_%s" n
+ | Int64 n -> pr ", c_%s" n
+ | Path n -> pr ", c_%s" n
+ | SockAddrAndLen (n, len) -> pr ", c_%s, c_%s" n len
+ | String n -> pr ", c_%s" n
+ | StringList n -> pr ", c_%s" n
+ | UInt n -> pr ", c_%s" n
+ | UInt32 n -> pr ", c_%s" n
+ | UInt64 n -> pr ", c_%s" n
+ ) args;
+ List.iter (
+ function
+ | OClosure { cbname} -> pr ", c_%s" cbname
+ | OFlags (n, _) -> pr ", c_%s" n
+ ) optargs;
+ pr ")\n";
+ let errcode = go_ret_c_errcode ret in
+ (match errcode with
+ | None -> ()
+ | Some errcode ->
+ pr " if ret == %s {\n" errcode;
+ pr " err := get_error (\"%s\", c_err)\n" name;
+ pr " C.free_error (&c_err)\n";
+ pr " return %s, err\n" (go_ret_error ret);
+ pr " }\n";
+ );
+ (match ret with
+ | RBool ->
+ pr " r := int (ret)\n";
+ pr " if r != 0 { return true, nil } else { return false, nil
}\n"
+ | RStaticString ->
+ pr " /* ret is statically allocated, do not free it. */\n";
+ pr " r := C.GoString (ret);\n";
+ pr " return &r, nil\n"
+ | RErr ->
+ pr " /* Note that the return value 0 has no meaning
here.\n";
+ pr " * It is only returned for consistency.\n";
+ pr " */\n";
+ pr " return 0, nil\n"
+ | RFd ->
+ pr " return int/*XXX*/ (ret), nil\n"
+ | RInt ->
+ pr " return int (ret), nil\n"
+ | RInt64 ->
+ pr " return int64 (ret), nil\n"
+ | RCookie ->
+ pr " return int64 (ret), nil\n"
+ | RString ->
+ pr " r := C.GoString (ret)\n";
+ pr " C.free (unsafe.Pointer (ret))\n";
+ pr " return &r, nil\n"
+ | RUInt ->
+ pr " return uint (ret), nil\n"
+ );
+ pr "}\n";
+ pr "\n"
+
let generate_golang_libnbd_go () generate_header CStyle;
@@ -62,14 +360,20 @@ free_error (struct error *err)
static struct nbd_handle *
_nbd_create_wrapper (struct error *err)
{
- struct nbd_handle *r;
+ struct nbd_handle *ret;
- r = nbd_create ();
- if (r == NULL)
+ ret = nbd_create ();
+ if (ret == NULL)
save_error (err);
- return r;
+ return ret;
}
+";
+
+ (* Wrappers. *)
+ List.iter print_wrapper handle_calls;
+
+ pr "\
// There must be no blank line between end comment and import!
// https://github.com/golang/go/issues/9733
*/
@@ -79,6 +383,7 @@ import (
\"fmt\"
\"runtime\"
\"syscall\"
+ \"unsafe\"
)
/* Handle. */
@@ -147,4 +452,27 @@ func (h *Libnbd) Close () *LibnbdError {
return nil
}
+/* Functions for translating between NULL-terminated lists of
+ * C strings and golang []string.
+ */
+func arg_string_list (xs []string) **C.char {
+ r := make ([]*C.char, 1 + len (xs))
+ for i, x := range xs {
+ r[i] = C.CString (x)
+ }
+ r[len (xs)] = nil
+ return &r[0]
+}
+
+func free_string_list (argv **C.char) {
+ for *argv != nil {
+ //C.free (*argv)
+ argv = (**C.char) (unsafe.Pointer (uintptr (unsafe.Pointer (argv)) +
+ unsafe.Sizeof (*argv)))
+ }
+}
+
";
+
+ (* Bindings. *)
+ List.iter print_binding handle_calls;
diff --git a/golang/src/libguestfs.org/libnbd/libnbd_200_connect_command_test.go
b/golang/src/libguestfs.org/libnbd/libnbd_200_connect_command_test.go
new file mode 100644
index 0000000..9faf244
--- /dev/null
+++ b/golang/src/libguestfs.org/libnbd/libnbd_200_connect_command_test.go
@@ -0,0 +1,35 @@
+/* libnbd golang tests
+ * 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.
+ */
+
+package libnbd
+
+import "testing"
+
+func Test200ConnectCommand (t *testing.T) {
+ h, err := Create ()
+ if err != nil {
+ t.Errorf ("could not create handle: %s", err)
+ }
+ _, err = h.Connect_command ([]string{
+ "nbdkit", "-s", "--exit-with-parent",
"-v", "null",
+ })
+ if err != nil {
+ t.Errorf ("could not connect: %s", err)
+ }
+ h.Close ()
+}
--
2.25.0
Daniel P. Berrangé
2020-Mar-18 09:32 UTC
Re: [Libguestfs] [PATCH libnbd v2 2/3] Add outline framework for Go language bindings (golang).
On Tue, Mar 17, 2020 at 09:20:12PM +0000, Richard W.M. Jones wrote:> + > +/* > +#cgo CFLAGS: > +#cgo LDFLAGS: -lnbdI 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/get.go?m=text > + */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: https://golang.org/pkg/go/build/ Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Daniel P. Berrangé
2020-Mar-18 09:37 UTC
Re: [Libguestfs] [PATCH libnbd v2 3/3] golang: Add straightforward bindings, without callbacks.
On Tue, Mar 17, 2020 at 09:20:13PM +0000, Richard W.M. Jones wrote:> + | Fd _ -> "int/*XXX*/"snip.> + | RFd -> "int/*XXX*/"snip.> + | RFd -> "0/*XXX*/"snip.> + | RFd -> Some "-1/*XXX*/"snip. For passing file descriptors in or out of Go APIs you'll want to use the os.File object. To pass it from Go to C use a param 'file os.File' and call 'C.int(file.Fd())' to get the POSIX file descriptor to pass to C. libvirt-go OpenGraphics API gives an illustration of this. For the reverse direction from C to Go use os.NewFile(uintptr(fd), "name") where 'name' is any sensibiel identifying short name. libvirt-go OpenGraphicsFD gives an illustration of this direction. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Maybe Matching Threads
- [PATCH libnbd] Add outline framework for Go language bindings (golang).
- [PATCH libnbd v2 0/3] Unfinished golang bindings.
- [PATCH libnbd v3] Add Go language bindings (golang) (RHBZ#1814538).
- [PATCH 2/2] golang: Don't run launch test if appliance has not been built.
- [PATCH libnbd v4] Add Go language bindings (golang) (RHBZ#1814538).