From 546763ffbc333b98808802fff0d601d018763d0c Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sun, 20 Mar 2022 15:04:27 -0500 Subject: [PATCH] [Go] Add an example for goin and godirectorin Shows how to use a go directory for passing an NULL terminated argv type array. This also exercises the bug in the previous commit. That's why the call1 function isn't assigned to zero, that the only case where that bug happens. Signed-off-by: Corey Minyard --- Examples/go/check.list | 1 + Examples/go/goin/Makefile | 18 ++++++ Examples/go/goin/example.i | 106 ++++++++++++++++++++++++++++++++++++ Examples/go/goin/index.html | 26 +++++++++ Examples/go/goin/runme.go | 38 +++++++++++++ Examples/go/index.html | 1 + 6 files changed, 190 insertions(+) create mode 100644 Examples/go/goin/Makefile create mode 100644 Examples/go/goin/example.i create mode 100644 Examples/go/goin/index.html create mode 100644 Examples/go/goin/runme.go diff --git a/Examples/go/check.list b/Examples/go/check.list index b3f34b306..6046c8310 100644 --- a/Examples/go/check.list +++ b/Examples/go/check.list @@ -12,3 +12,4 @@ reference simple template variables +goin diff --git a/Examples/go/goin/Makefile b/Examples/go/goin/Makefile new file mode 100644 index 000000000..f79b083cb --- /dev/null +++ b/Examples/go/goin/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/goin/example.i b/Examples/go/goin/example.i new file mode 100644 index 000000000..1d8289af8 --- /dev/null +++ b/Examples/go/goin/example.i @@ -0,0 +1,106 @@ + +%module(directors="1") example + +%inline %{ +// Helper functions for converting string arrays +#include +void *alloc_ptr_array(unsigned int len) +{ + return calloc(len, sizeof(void *)); +} +void set_ptr_array(void *ain, unsigned int pos, void *val) +{ + void **a = (void **) ain; + a[pos] = val; +} +void *get_ptr_array(void *ain, unsigned int pos) +{ + void **a = (void **) ain; + return a[pos]; +} +void free_ptr_array(void *ain) +{ + void **a = (void **) ain; + unsigned int i; + + if (!a) + return; + for (i = 0; a[i]; i++) { + free(a[i]); + } + free(a); +} +char *uintptr_to_string(void *in) +{ + return (char *) in; +} +void *string_to_uintptr(char *in) +{ + return strdup(in); +} +%} + +// These typemaps convert between an array of strings in Go and a +// const char** that is NULL terminated in C++. +%typemap(gotype) (const char * const *) "[]string"; +%typemap(imtype) (const char * const *) "uintptr"; +%typemap(goin) (const char * const *) { + if $input == nil || len($input) == 0 { + $result = 0 + } else { + $result = Alloc_ptr_array(uint(len($input) + 1)) + defer func() { + Free_ptr_array($result) + }() + var i uint + for i = 0; i < uint(len($input)); i++ { + Set_ptr_array($result, i, String_to_uintptr($input[i])) + } + } +} +%typemap(in) (const char * const *) { + $1 = (char **) $input; +} +%typemap(godirectorin) (const char * const *) { + if ($input == 0) { + $result = nil + } else { + var i uint + for i = 0; ; i++ { + var v uintptr = Get_ptr_array($input, i) + if v == 0 { + break + } + } + if i == 0 { + $result = nil + } else { + $result = make([]string, i) + for i = 0; ; i++ { + var v uintptr = Get_ptr_array($input, i) + if v == 0 { + break + } + $result[i] = Uintptr_to_string(v) + } + } + } +} + +%feature("director") callbacks; + +%inline %{ + class callbacks { + public: + virtual bool call1(int v, const char * const *strarray); + virtual ~callbacks() {} + }; + + bool check1(callbacks *c, int v, const char * const *strarray) { + return c->call1(v, strarray); + } + + bool callbacks::call1(int v, const char * const *strarray) { + return false; + } +%} diff --git a/Examples/go/goin/index.html b/Examples/go/goin/index.html new file mode 100644 index 000000000..852b068da --- /dev/null +++ b/Examples/go/goin/index.html @@ -0,0 +1,26 @@ + + +SWIG:Examples:go:going + + + + + +SWIG/Examples/go/goin/ +
+ +

Example of using goin and godirectorin

+ +

+This example converts between a Go []string and a "const char * const *" +in C/C++. It does this for a director and for a normal call. + +

+

+ +
+ + diff --git a/Examples/go/goin/runme.go b/Examples/go/goin/runme.go new file mode 100644 index 000000000..dfc7b0936 --- /dev/null +++ b/Examples/go/goin/runme.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "swigtests/example" +) + +type mycallbacks struct { + example.Callbacks +} + +var tststrs = []string{ "A", "BCD", "EFGH" } +var tstint int = 5 + +func (v *mycallbacks) Call1(val int, strarray []string) bool { + var rv bool = true + + for i, s := range strarray { + fmt.Printf("%d: %s\n", i, s) + if s != tststrs[i] { + fmt.Printf(" ***Mismatch, expected %s\n", tststrs[i]) + rv = false + } + } + if val != tstint { + rv = false + } + return rv +} + +func main() { + cbs := &mycallbacks{} + cbs.Callbacks = example.NewDirectorCallbacks(cbs) + worked := example.Check1(cbs, tstint, tststrs) + if !worked { + panic("Data mismatch") + } +} diff --git a/Examples/go/index.html b/Examples/go/index.html index 467f4ecb7..370424c54 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -24,6 +24,7 @@ certain C declarations are turned into constants.
  • callback. C++ callbacks using directors.
  • extend. Polymorphism using directors.
  • director. Example how to utilize the director feature. +
  • director. Example how to use goin and godirectorin.

    Compilation Issues