Repository: go
Issue: runtime: make it possible to know the go initialization in shared libraries is finished without calling a go function
Labels: compiler/runtime

Please see [golang-nuts › How to export C variables from Go shared libraries?](https://groups.google.com/d/msg/golang-nuts/IAw-d5mXzk8/7QpXyPAa930J) for discussion.

I tried to write a Go shared library to make Apache or nginx modules.
What I would like to do is exporting a C struct variable, not a C function, from a Go shared library.
#1. What version of Go are you using (go version)?

1.5beta2

```
$ go version
go version go1.5beta2 linux/amd64
```
#2. What operating system and processor architecture are you using?

Ubuntu Linux trusty amd64

```
$ uname -a
Linux vagrant-ubuntu-trusty-64 3.13.0-55-generic #92-Ubuntu SMP Sun Jun 14 18:32:20 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
```
#3. What did you do?

Open a Go shared library written from a C main program. Please refer to the commit https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/tree/0972d57461b091aed35c9ed083af0edae0c885cc for source codes.

[runtime_load.c](https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/blob/1951dfb411dcff8986687ca98f801505397fc6cf/Makefile)

```
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
    printf("runtime_load started\n");
    void *handle = dlopen("libgodll.so", RTLD_LAZY);
    if (!handle) {
        printf("dlopen failed\n");
        return 1;
    }
    printf("after dlopen. handle=%llx\n", (long long unsigned)handle);
    int *i_ptr = dlsym(handle, "i");
    printf("i=%d\n", *i_ptr);
#ifndef NO_DLCLOSE
    printf("calling dlclose\n");
    dlclose(handle);
    printf("after dlclose\n");
#endif
    return 0;
}
```

[libgodll.go](https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/blob/1951dfb411dcff8986687ca98f801505397fc6cf/libgodll.go)

```
package main

// int i;
import "C"

func init() {
    C.i = 1
}

//export libInit
func libInit() {}

func main() {}
```

[Makefile](https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/blob/1951dfb411dcff8986687ca98f801505397fc6cf/Makefile)

```
test_runtime: runtime_load libgodll.so
    LD_LIBRARY_PATH=. ./runtime_load
    echo status=$$?

test_compiletime: compiletime_load libgodll.so
    LD_LIBRARY_PATH=. ./compiletime_load
    echo status=$$?

runtime_load: runtime_load.c
    $(CC) -o runtime_load runtime_load.c $(CFLAGS) -ldl

compiletime_load: libgodll.so compiletime_load.c
    $(CC) -o compiletime_load compiletime_load.c -L. -lgodll

libgodll.so: libgodll.go
    go build -buildmode=c-shared -o libgodll.so libgodll.go

clean:
    -rm runtime_load compileitme_load core libgodll.h libgodll.so
```

With these source codes above, I ran `make test_runtime`
#4. What did you expect to see?

I expect to see `i=1` is printed at https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/blob/0972d57461b091aed35c9ed083af0edae0c885cc/runtime_load.c#L13
#5. What did you see instead?

Actually `i=0` is printed at https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/blob/0972d57461b091aed35c9ed083af0edae0c885cc/runtime_load.c#L13
Please see https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/tree/0972d57461b091aed35c9ed083af0edae0c885cc#load-a-shared-library-at-runtime-using-dlopen for the whole output.

When I added `usleep(1000 * 1000)` between `dlopen` and referencing `i`, `i=1` is printed at https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/blob/1951dfb411dcff8986687ca98f801505397fc6cf/runtime_load.c#L14
Please see https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/tree/1951dfb411dcff8986687ca98f801505397fc6cf#load-a-shared-library-at-runtime-using-dlopen for the whole output.

Please refer to the commit https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/tree/1951dfb411dcff8986687ca98f801505397fc6cf for source codes.

[runtime_load.c](https://github.com/hnakamur/export_c_variable_from_go_dll_experiment/blob/1951dfb411dcff8986687ca98f801505397fc6cf/runtime_load.c)

```
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
    printf("runtime_load started\n");
    void *handle = dlopen("libgodll.so", RTLD_LAZY);
    if (!handle) {
        printf("dlopen failed\n");
        return 1;
    }
    printf("after dlopen. handle=%llx\n", (long long unsigned)handle);
    usleep(1000 * 1000);
    int *i_ptr = dlsym(handle, "i");
    printf("i=%d\n", *i_ptr);
#ifndef NO_DLCLOSE
    printf("calling dlclose\n");
    dlclose(handle);
    printf("after dlclose\n");
#endif
    return 0;
}
```

I would like to know when the Go initialization of shared libraries is finished without calling a Go function.

Ideally, I would like to set values of C variables at Go shared library compile time, instead of updating values of C variables with `init()` in a Go shared library.