Merge pull request #2241 from cminyard/add-goin-newline
[Go] Add missing newlines for goin typemaps
This commit is contained in:
commit
05580ff1e7
10 changed files with 315 additions and 3 deletions
|
|
@ -7,6 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
||||||
Version 4.1.0 (in progress)
|
Version 4.1.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2022-04-20: cminyard
|
||||||
|
Fix an issue where newlines were not properly generated
|
||||||
|
for godirectorin typemaps. If you have a virtual function
|
||||||
|
not assigned to zero, in some cases it won't generate a
|
||||||
|
newline and you will see errors:
|
||||||
|
example.go:1508:3: expected ';', found swig_r
|
||||||
|
when compiling the go code.
|
||||||
|
|
||||||
|
Also add an example of using goin and godirectorin and add
|
||||||
|
a test for this situation.
|
||||||
|
|
||||||
2022-04-11: robinst
|
2022-04-11: robinst
|
||||||
#2257 Fix new Ruby 3.2 warning "undefining the allocator of T_DATA
|
#2257 Fix new Ruby 3.2 warning "undefining the allocator of T_DATA
|
||||||
class swig_runtime_data".
|
class swig_runtime_data".
|
||||||
|
|
|
||||||
|
|
@ -12,3 +12,4 @@ reference
|
||||||
simple
|
simple
|
||||||
template
|
template
|
||||||
variables
|
variables
|
||||||
|
goin
|
||||||
|
|
|
||||||
18
Examples/go/goin/Makefile
Normal file
18
Examples/go/goin/Makefile
Normal file
|
|
@ -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
|
||||||
106
Examples/go/goin/example.i
Normal file
106
Examples/go/goin/example.i
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
|
||||||
|
%module(directors="1") example
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
// Helper functions for converting string arrays
|
||||||
|
#include <stdlib.h>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
%}
|
||||||
26
Examples/go/goin/index.html
Normal file
26
Examples/go/goin/index.html
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>SWIG:Examples:go:going</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#ffffff">
|
||||||
|
|
||||||
|
|
||||||
|
<tt>SWIG/Examples/go/goin/</tt>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<H2>Example of using goin and godirectorin</H2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="example.i">example.i</a>. SWIG interface file.
|
||||||
|
<li><a href="runme.go">runme.go</a>. Sample Go program.
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
38
Examples/go/goin/runme.go
Normal file
38
Examples/go/goin/runme.go
Normal file
|
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@ certain C declarations are turned into constants.
|
||||||
<li><a href="callback/index.html">callback</a>. C++ callbacks using directors.
|
<li><a href="callback/index.html">callback</a>. C++ callbacks using directors.
|
||||||
<li><a href="extend/index.html">extend</a>. Polymorphism using directors.
|
<li><a href="extend/index.html">extend</a>. Polymorphism using directors.
|
||||||
<li><a href="director/index.html">director</a>. Example how to utilize the director feature.
|
<li><a href="director/index.html">director</a>. Example how to utilize the director feature.
|
||||||
|
<li><a href="goin/index.html">director</a>. Example how to use goin and godirectorin.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Compilation Issues</h2>
|
<h2>Compilation Issues</h2>
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,15 @@ func (p *GoMyClass) S3(s *string) {
|
||||||
*s = "R3"
|
*s = "R3"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *GoMyClass) S4(s []string) {
|
||||||
|
if s[0] != "T1" {
|
||||||
|
panic(s)
|
||||||
|
}
|
||||||
|
if s[1] != "T2" {
|
||||||
|
panic(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
a := wrap.NewDirectorMyClass(&GoMyClass{})
|
a := wrap.NewDirectorMyClass(&GoMyClass{})
|
||||||
m := map[string]interface{}{
|
m := map[string]interface{}{
|
||||||
|
|
@ -56,6 +65,8 @@ func main() {
|
||||||
panic(str)
|
panic(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.CallS4([]string{ "T1", "T2" })
|
||||||
|
|
||||||
a = wrap.NewDirectorMyClass(nil)
|
a = wrap.NewDirectorMyClass(nil)
|
||||||
s = a.Adjust(m)
|
s = a.Adjust(m)
|
||||||
if s.Str != `{"first":"second"}` {
|
if s.Str != `{"first":"second"}` {
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,92 @@ type GoRetStruct struct {
|
||||||
$1.assign(tmp->p, tmp->p + tmp->n);
|
$1.assign(tmp->p, tmp->p + tmp->n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
// Helper functions for converting string arrays
|
||||||
|
#include <stdlib.h>
|
||||||
|
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") MyClass;
|
%feature("director") MyClass;
|
||||||
|
|
||||||
%inline
|
%inline
|
||||||
|
|
@ -134,9 +220,23 @@ class MyClass {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void S1(std::string s) = 0;
|
void CallS4(const char * const *strarray);
|
||||||
|
virtual void S1(std::string s);
|
||||||
virtual void S2(std::string& s) = 0;
|
virtual void S2(std::string& s) = 0;
|
||||||
virtual void S3(std::string* s) = 0;
|
virtual void S3(std::string* s) = 0;
|
||||||
|
virtual void S4(const char * const *strarray);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void MyClass::S1(std::string s) {
|
||||||
|
throw "Base S1 called!";
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyClass::S4(const char * const *strarray) {
|
||||||
|
throw "Base S4 called!";
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyClass::CallS4(const char * const *strarray) {
|
||||||
|
this->S4(strarray);
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
|
||||||
|
|
@ -3518,7 +3518,7 @@ private:
|
||||||
goin = Copy(goin);
|
goin = Copy(goin);
|
||||||
Replaceall(goin, "$input", ln);
|
Replaceall(goin, "$input", ln);
|
||||||
Replaceall(goin, "$result", ivar);
|
Replaceall(goin, "$result", ivar);
|
||||||
Printv(f_go_wrappers, goin, NULL);
|
Printv(f_go_wrappers, goin, "\n", NULL);
|
||||||
Delete(goin);
|
Delete(goin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3772,7 +3772,7 @@ private:
|
||||||
goin = Copy(goin);
|
goin = Copy(goin);
|
||||||
Replaceall(goin, "$input", ln);
|
Replaceall(goin, "$input", ln);
|
||||||
Replaceall(goin, "$result", ivar);
|
Replaceall(goin, "$result", ivar);
|
||||||
Printv(f_go_wrappers, goin, NULL);
|
Printv(f_go_wrappers, goin, "\n", NULL);
|
||||||
Delete(goin);
|
Delete(goin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue