bind/objc: remove a constructor and retain blocks

A framework generated with gomobile bind -target=ios has two global
constructors: one initializing a data structure and another using it.
These constructors are defined in different translation units, which
(I believe, reasoning from C++ global constructors) means their order
of initialization is undefined.

A capturing block is stack allocated. Its memory is invalid after the
function returns. Make a copy of the interface initializer blocks so
they can be saved to the heap.

Block implementation background:
http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

Updates golang/go#12590

Change-Id: Ia7ae9f4bbd8df6e6e79949de54b3e6c48148c700
Reviewed-on: https://go-review.googlesource.com/14549
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
David Crawshaw 2015-09-14 20:55:15 -04:00
Родитель b10f681911
Коммит 7a70f37cf6
1 изменённых файлов: 12 добавлений и 7 удалений

Просмотреть файл

@ -88,15 +88,17 @@
// registered by calling go_seq_register_proxy from a global contructor funcion.
static goSeqDictionary *proxies = NULL;
__attribute__((constructor)) static void go_seq_very_init() {
proxies = [[goSeqDictionary alloc] init];
}
void go_seq_register_proxy(const char *descriptor,
void (*fn)(id, int, GoSeq *, GoSeq *)) {
[proxies put:^(id obj, int code, GoSeq *in, GoSeq *out) {
if (proxies == NULL) {
proxies = [[goSeqDictionary alloc] init];
}
// Copying moves the block to the heap.
id block = [^(id obj, int code, GoSeq *in, GoSeq *out) {
fn(obj, code, in, out);
} withKey:[NSString stringWithUTF8String:descriptor]];
} copy];
[proxies put:block withKey:[NSString stringWithUTF8String:descriptor]];
}
// RefTracker encapsulates a map of objective-C objects passed to Go and
@ -322,7 +324,10 @@ void go_seq_recv(int32_t refnum, const char *desc, int code, uint8_t *in_ptr,
NSString *k = [NSString stringWithUTF8String:desc];
proxyFn fn = [proxies get:k];
proxyFn fn = NULL;
if (proxies != NULL) {
fn = [proxies get:k];
}
if (fn == NULL) {
LOG_FATAL(@"cannot find a proxy function for %s", desc);
return;