diff --git a/bind/objc/SeqTest.m b/bind/objc/SeqTest.m index 6c64bb2..d814ee2 100644 --- a/bind/objc/SeqTest.m +++ b/bind/objc/SeqTest.m @@ -27,6 +27,18 @@ void testHello(NSString *input) { } } +void testBytesAppend(NSString *a, NSString *b) { + NSData *data_a = [a dataUsingEncoding:NSUTF8StringEncoding]; + NSData *data_b = [b dataUsingEncoding:NSUTF8StringEncoding]; + NSData *gotData = GoTestpkg_BytesAppend(data_a, data_b); + NSString *got = + [[NSString alloc] initWithData:gotData encoding:NSUTF8StringEncoding]; + NSString *want = [a stringByAppendingString:b]; + if (![got isEqualToString:want]) { + ERROR(@"want %@\nGoTestpkg_BytesAppend(%@, %@) = %@", want, a, b, got); + } +} + // Invokes functions and object methods defined in Testpkg.h. // // TODO(hyangah): apply testing framework (e.g. XCTestCase) @@ -48,6 +60,8 @@ int main(void) { 0xD83D, 0xDCA9, }; // utf-16, pile of poo. testHello([NSString stringWithCharacters:t length:2]); + + testBytesAppend(@"Foo", @"Bar"); } fprintf(stderr, "%s\n", err ? "FAIL" : "PASS"); diff --git a/bind/objc/seq.h b/bind/objc/seq.h index d6cb474..27ec9d3 100644 --- a/bind/objc/seq.h +++ b/bind/objc/seq.h @@ -22,6 +22,7 @@ extern int64_t go_seq_readInt64(GoSeq *seq); extern float go_seq_readFloat32(GoSeq *seq); extern double go_seq_readFloat64(GoSeq *seq); extern NSString *go_seq_readUTF8(GoSeq *seq); +extern NSData *go_seq_readByteArray(GoSeq *seq); extern void go_seq_writeInt8(GoSeq *seq, int8_t v); extern void go_seq_writeInt16(GoSeq *seq, int16_t v); @@ -31,6 +32,10 @@ extern void go_seq_writeFloat32(GoSeq *seq, float v); extern void go_seq_writeFloat64(GoSeq *seq, double v); extern void go_seq_writeUTF8(GoSeq *seq, NSString *v); +// go_seq_writeByteArray writes the data bytes to the seq. Note that the +// data should be valid until the the subsequent go_seq_send call completes. +extern void go_seq_writeByteArray(GoSeq *seq, NSData *data); + // go_seq_send sends a function invocation request to Go. // It blocks until the function completes. // If the request is for a method, the first element in req is diff --git a/bind/objc/seq_darwin.m b/bind/objc/seq_darwin.m index 9e6ad87..35b081d 100644 --- a/bind/objc/seq_darwin.m +++ b/bind/objc/seq_darwin.m @@ -191,6 +191,28 @@ void go_seq_writeUTF8(GoSeq *seq, NSString *s) { return; } +NSData *go_seq_readByteArray(GoSeq *seq) { + int64_t sz = *MEM_READ(seq, int64_t); + if (sz == 0) { + return [NSData data]; + } + // BUG(hyangah): it is possible that *ptr is already GC'd by Go runtime. + void *ptr = (void *)(*MEM_READ(seq, int64_t)); + return [NSData dataWithBytes:ptr length:sz]; +} + +void go_seq_writeByteArray(GoSeq *seq, NSData *data) { + int64_t sz = data.length; + MEM_WRITE(seq, int64_t) = sz; + if (sz == 0) { + return; + } + + int64_t ptr = data.bytes; + MEM_WRITE(seq, int64_t) = ptr; + return; +} + void go_seq_send(char *descriptor, int code, GoSeq *req_seq, GoSeq *res_seq) { if (descriptor == NULL) { LOG_FATAL(@"invalid NULL descriptor"); diff --git a/bind/objc/testpkg/go_testpkg/go_testpkg.go b/bind/objc/testpkg/go_testpkg/go_testpkg.go index 887362d..d70ad82 100644 --- a/bind/objc/testpkg/go_testpkg/go_testpkg.go +++ b/bind/objc/testpkg/go_testpkg/go_testpkg.go @@ -13,6 +13,13 @@ import ( "golang.org/x/mobile/bind/seq" ) +func proxy_BytesAppend(out, in *seq.Buffer) { + param_a := in.ReadByteArray() + param_b := in.ReadByteArray() + res := testpkg.BytesAppend(param_a, param_b) + out.WriteByteArray(res) +} + func proxy_Hello(out, in *seq.Buffer) { param_s := in.ReadString() res := testpkg.Hello(param_s) @@ -36,8 +43,9 @@ func proxy_Sum(out, in *seq.Buffer) { } func init() { - seq.Register("testpkg", 1, proxy_Hello) - seq.Register("testpkg", 2, proxy_Hi) - seq.Register("testpkg", 3, proxy_Int) - seq.Register("testpkg", 4, proxy_Sum) + seq.Register("testpkg", 1, proxy_BytesAppend) + seq.Register("testpkg", 2, proxy_Hello) + seq.Register("testpkg", 3, proxy_Hi) + seq.Register("testpkg", 4, proxy_Int) + seq.Register("testpkg", 5, proxy_Sum) } diff --git a/bind/objc/testpkg/objc_testpkg/GoTestpkg.h b/bind/objc/testpkg/objc_testpkg/GoTestpkg.h index a5bf2e6..45d1eaa 100644 --- a/bind/objc/testpkg/objc_testpkg/GoTestpkg.h +++ b/bind/objc/testpkg/objc_testpkg/GoTestpkg.h @@ -9,6 +9,7 @@ #include "seq.h" +FOUNDATION_EXPORT NSData *GoTestpkg_BytesAppend(NSData *a, NSData *b); FOUNDATION_EXPORT void GoTestpkg_Hi(); FOUNDATION_EXPORT void GoTestpkg_Int(int32_t x); FOUNDATION_EXPORT int64_t GoTestpkg_Sum(int64_t x, int64_t y); diff --git a/bind/objc/testpkg/objc_testpkg/GoTestpkg.m b/bind/objc/testpkg/objc_testpkg/GoTestpkg.m index 6d7bff7..b92f946 100644 --- a/bind/objc/testpkg/objc_testpkg/GoTestpkg.m +++ b/bind/objc/testpkg/objc_testpkg/GoTestpkg.m @@ -11,10 +11,11 @@ #define _DESCRIPTOR_ "testpkg" -#define _CALL_Hello_ 1 -#define _CALL_Hi_ 2 -#define _CALL_Int_ 3 -#define _CALL_Sum_ 4 +#define _CALL_BytesAppend_ 1 +#define _CALL_Hello_ 2 +#define _CALL_Hi_ 3 +#define _CALL_Int_ 4 +#define _CALL_Sum_ 5 #define INIT_SEQ(X) \ GoSeq X; \ @@ -22,6 +23,19 @@ #define FREE_SEQ(X) go_seq_free(&X); +NSData *GoTestpkg_BytesAppend(NSData *a, NSData *b) { + INIT_SEQ(in); + INIT_SEQ(out); + go_seq_writeByteArray(&in, a); + go_seq_writeByteArray(&in, b); + go_seq_send(_DESCRIPTOR_, _CALL_BytesAppend_, &in, &out); + + NSData *ret = go_seq_readByteArray(&out); + FREE_SEQ(out); + FREE_SEQ(in); + return ret; +} + void GoTestpkg_Hi() { // No input, output. go_seq_send(_DESCRIPTOR_, _CALL_Hi_, NULL, NULL); diff --git a/bind/objc/testpkg/testpkg.go b/bind/objc/testpkg/testpkg.go index 43df6e9..9750003 100644 --- a/bind/objc/testpkg/testpkg.go +++ b/bind/objc/testpkg/testpkg.go @@ -23,3 +23,7 @@ func Sum(x, y int64) int64 { func Hello(s string) string { return fmt.Sprintf("Hello, %s!", s) } + +func BytesAppend(a []byte, b []byte) []byte { + return append(a, b...) +}