[Go] Add goargout typemap.

This commit is contained in:
Ian Lance Taylor 2014-09-09 11:28:04 -07:00
commit acaaa0f31f
6 changed files with 286 additions and 44 deletions

View file

@ -32,4 +32,12 @@ func main() {
fmt.Println("got", m, "want", want)
panic(m)
}
a := []string{"a", "bc", "def"}
go_inout.DoubleArray(&a)
dwant := []string{"a", "bc", "def", "aa", "bcbc", "defdef"}
if !reflect.DeepEqual(a, dwant) {
fmt.Println("got", a, "want", dwant)
panic(a)
}
}

View file

@ -1,9 +1,11 @@
// Test the goin and goout typemaps.
// Test the goin, goout, and goargout typemaps.
%module go_inout
%{
#include <string>
#include <vector>
#include <stdint.h>
%}
%inline
@ -21,7 +23,7 @@ struct RetStruct {
// Write a typemap that calls C++ by converting in and out of JSON.
%go_import("encoding/json")
%go_import("encoding/json", "bytes", "encoding/binary")
%insert(go_header)
%{
@ -77,3 +79,121 @@ RetStruct Same(MyStruct s)
}
%}
%inline
%{
struct MyArray {
std::vector<std::string> strings;
};
static uint64_t getuint64(const char* s) {
uint64_t ret = 0;
for (int i = 0; i < 8; i++, s++) {
ret |= static_cast<uint64_t>(*s) << i * 8;
}
return ret;
}
static void putuint64(std::string *s, size_t off, uint64_t v) {
for (int i = 0; i < 8; i++) {
(*s)[off + i] = (v >> (i * 8)) & 0xff;
}
}
%}
%typemap(gotype) MyArray* "*[]string"
%typemap(imtype) MyArray* "*string"
// Encode the slice as a single string, with length prefixes.
%typemap(goin) MyArray*
%{
{
var buf bytes.Buffer
bin := binary.LittleEndian
var b [8]byte
bin.PutUint64(b[:], uint64(len(*$input)))
buf.Write(b[:])
for _, s := range *$input {
bin.PutUint64(b[:], uint64(len(s)))
buf.Write(b[:])
buf.WriteString(s)
}
str := buf.String()
$result = &str
}
%}
// Unpack the string holding the packed slice.
%typemap(in) MyArray* (MyArray t)
%{
{
_gostring_ *s = $input;
const char *p = static_cast<const char *>(s->p);
uint64_t len = getuint64(p);
p += 8;
t.strings.resize(len);
for (uint64_t i = 0; i < len; i++) {
uint64_t slen = getuint64(p);
p += 8;
t.strings[i].assign(p, slen);
p += slen;
}
$1 = &t;
}
%}
// Pack the vector into a string.
%typemap(argout) MyArray*
%{
{
size_t tot = 8;
std::vector<std::string>::const_iterator p;
for (p = $1->strings.begin(); p != $1->strings.end(); ++p) {
tot += 8 + p->size();
}
std::string str;
str.resize(tot);
putuint64(&str, 0, $1->strings.size());
size_t off = 8;
for (p = $1->strings.begin(); p != $1->strings.end(); ++p) {
putuint64(&str, off, p->size());
off += 8;
str.replace(off, p->size(), *p);
off += p->size();
}
*$input = _swig_makegostring(str.data(), str.size());
}
%}
// Unpack the string into a []string.
%typemap(goargout) MyArray*
%{
{
str := *$input
bin := binary.LittleEndian
size := bin.Uint64([]byte(str[:8]))
str = str[8:]
r := make([]string, size)
for i := range r {
len := bin.Uint64([]byte(str[:8]))
str = str[8:]
r[i] = str[:len]
str = str[len:]
}
*$1 = r
}
%}
%inline
%{
void DoubleArray(MyArray* v) {
size_t size = v->strings.size();
for (size_t i = 0; i < size; i++) {
v->strings.push_back(v->strings[i] + v->strings[i]);
}
}
%}