This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: Using Go to build a shared library to be called from C
- From: Ian Lance Taylor <iant at google dot com>
- To: LRN <lrn1986 at gmail dot com>
- Cc: gcc-help at gcc dot gnu dot org
- Date: Thu, 27 Oct 2011 12:37:43 -0700
- Subject: Re: Using Go to build a shared library to be called from C
- References: <4DF6362F.7030003@gmail.com> <mcr1uyxtof9.fsf@coign.corp.google.com> <CAFQHNFd8FjkyVOSPsuq79nMQVzPnH4N8RaU8QpDtWj2ryyKtDw@mail.gmail.com>
LRN <lrn1986@gmail.com> writes:
> On Tue, Jun 14, 2011 at 1:24 AM, Ian Lance Taylor <iant@google.com> wrote:
>> LRN <lrn1986@gmail.com> writes:
>>
>>> However, if i put anything more complex than "return 1" into Myfunc in
>>> Go (such as using fmt.Printf() or returning a string - with
>>> appropriate prototype changes to 'string' and 'char*' in Go and C,
>>> naturally), it segfaults at runtime.
>>>
>>> Is that a limitation of gccgo, a bug, or am i simply doing something wrong?
>>
>> This is a current limitation of gccgo. ÂAt present nothing initializes
>> the packages imported by a packaged compiled into a shared library.
>> This is fixable with a bit of thought but is not high on the priority
>> list.
> How's it going? Any news.
The status is unchanged.
> As a side note, after discussing [1] static linking in Go (due to the
> fact that go doesn't have dynamic linking), i thought a bit, and came
> up with this:
>
> ---------main_shared.go
> package main_shared
>
> import (
> "fmt"
> )
>
> func Myfunc () string {
> return "result"
> }
>
> type ComplexType struct {
> somestring string
> someint int
> }
>
> func Myfunc2 (n int) (r ComplexType) {
> r.somestring = fmt.Sprintf ("a formatted version of integer %d", n)
> r.someint = n
> return
> }
> ---------end of main_shared.go
>
> ---------main_executable.go
> package main
>
> import (
> "fmt"
> )
>
> func myfunc () string __asm__ ("go.main_shared.Myfunc")
>
> type ComplexType struct {
> somestring string
> someint int
> }
>
> func myfunc2 (n int) (r ComplexType) __asm__ ("go.main_shared.Myfunc2")
>
> func main() {
> s := myfunc ()
> fmt.Printf ("Calling myfunc() resulted in a string %s\n", s)
> n := 5
> c := myfunc2 (n)
> fmt.Printf ("Passing %d to myfunc2() resulted in %s (with an integer
> %d)\n", n, c.somestring, c.someint)
> }
> ---------end of main_executable.go
>
> compile and run:
> gccgo -g -O0 -fPIC -shared main_shared.go -o libmain_shared.so -lgcc
> gccgo -g -O0 main_executable.go -o main -L. -lmain_shared
> LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
>
> and it prints:
> Calling myfunc() resulted in a string result
> Passing 5 to myfunc2() resulted in a formatted version of integer 5
> (with an integer 5)
>
> Which was expected.
>
> ldd says that the executable is linked to libgo and libmain_shared:
>
> $ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ldd ./main
> linux-vdso.so.1 => (0x00007fff9022b000)
> libmain_shared.so => ./libmain_shared.so (0x00007f0e4a7fa000)
> libgo.so.0 => /usr/lib/x86_64-linux-gnu/libgo.so.0 (0x00007f0e49bb7000)
> libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0e49934000)
> libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f0e4971e000)
> libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0e4939a000)
> /lib64/ld-linux-x86-64.so.2 (0x00007f0e4a9ff000)
> libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0e4917d000)
>
> I thought that since the problem lies in libgo not being initializing,
> then it should work with the main executable written in Go, because it
> does initialize its own runtime library, which is then shared with
> libmain_shared.
>
> My guess is that this will only work when both modules are linked to
> the same version of libgo.
Yes, it should work in that case, I think. I have not actually tried
it, though.
> Is it ever going to be a valid way of linking Go modules, or just a hack?
There will probably be a way to dynamically link Go modules at some
point, but I don't know when.
Ian