public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Using Go to build a shared library to be called from C
@ 2011-06-13 21:02 LRN
  2011-06-14  6:32 ` Ian Lance Taylor
  0 siblings, 1 reply; 6+ messages in thread
From: LRN @ 2011-06-13 21:02 UTC (permalink / raw)
  To: gcc-help

Using 
http://gcc.gnu.org/onlinedocs/gccgo/Function-Names.html#Function-Names 
i've been able to make a shared library written in Go:
-----main.go------
package main

func Myfunc () int32 {
   return 1
}
------------------

it's linked like this:
gccgo -shared main.go -o libmain.so -lgcc

and is used by this C program:
-----main.c-----
#include <stdio.h>
extern int Myfunc () __asm__ ("go.main.Myfunc");

int main (int argc, char **argv)
{
   int tmp;
   printf ("Calling the function\n");
   tmp = Myfunc ();
   printf ("Called the function, got %d\n", tmp);
   return 0;
}
---------------

which is linked like this:
gcc -g -O0 main.c -o main -L. -lmain

and when i run it like that:
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main

it works.

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?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using Go to build a shared library to be called from C
  2011-06-13 21:02 Using Go to build a shared library to be called from C LRN
@ 2011-06-14  6:32 ` Ian Lance Taylor
  2011-06-14  9:54   ` LRN
  2011-10-27 11:24   ` LRN
  0 siblings, 2 replies; 6+ messages in thread
From: Ian Lance Taylor @ 2011-06-14  6:32 UTC (permalink / raw)
  To: LRN; +Cc: gcc-help

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.

Ian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using Go to build a shared library to be called from C
  2011-06-14  6:32 ` Ian Lance Taylor
@ 2011-06-14  9:54   ` LRN
  2011-06-14 14:02     ` Ian Lance Taylor
  2011-10-27 11:24   ` LRN
  1 sibling, 1 reply; 6+ messages in thread
From: LRN @ 2011-06-14  9:54 UTC (permalink / raw)
  To: gcc-help

On 14.06.2011 1:24, Ian Lance Taylor 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.
While i certainly in no position tell the others what is high-priority 
and what isn't, i feel that i should point out that the ability to 
combine shared libraries written in Go with non-go programs would allow 
any software to leverage Go's abilities (mostly - its easy-to-use 
concurrency model, even if its implementation in gccgo is not efficient 
at the moment) by re-implementing some parts in Go, while keeping 
everything else in C (or whatever is being used).

Anyway, if this situation is not going to change for some time, it might 
be a good thing to update the documentation to make it clear what works 
and what doesn't.

Ah, and another thing. Does that apply to static linking as well? I 
suddenly realized that if it does, then why the hell the documentation 
even mentions C->Go interoperability?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using Go to build a shared library to be called from C
  2011-06-14  9:54   ` LRN
@ 2011-06-14 14:02     ` Ian Lance Taylor
  0 siblings, 0 replies; 6+ messages in thread
From: Ian Lance Taylor @ 2011-06-14 14:02 UTC (permalink / raw)
  To: LRN; +Cc: gcc-help

LRN <lrn1986@gmail.com> writes:

> Anyway, if this situation is not going to change for some time, it
> might be a good thing to update the documentation to make it clear
> what works and what doesn't.

Yes, probably a good idea.

> Ah, and another thing. Does that apply to static linking as well? I
> suddenly realized that if it does, then why the hell the documentation
> even mentions C->Go interoperability?

A Go program can call C functions just fine.  Those C functions can call
Go code.  The problem is when your main function is in C, or when you
use shared libraries written in Go.

Ian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using Go to build a shared library to be called from C
  2011-06-14  6:32 ` Ian Lance Taylor
  2011-06-14  9:54   ` LRN
@ 2011-10-27 11:24   ` LRN
  2011-10-27 19:38     ` Ian Lance Taylor
  1 sibling, 1 reply; 6+ messages in thread
From: LRN @ 2011-10-27 11:24 UTC (permalink / raw)
  To: gcc-help

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.

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.

Are there any other problems with this kind of linking?

Is it ever going to be a valid way of linking Go modules, or just a hack?

Also, it really makes me think about putting ComplexType definition
into separate file and calling it a "header" ... weird.

P.S. This time it didn't work without -fPIC for some reason.

[1] http://comments.gmane.org/gmane.comp.lang.go.general/41770

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using Go to build a shared library to be called from C
  2011-10-27 11:24   ` LRN
@ 2011-10-27 19:38     ` Ian Lance Taylor
  0 siblings, 0 replies; 6+ messages in thread
From: Ian Lance Taylor @ 2011-10-27 19:38 UTC (permalink / raw)
  To: LRN; +Cc: gcc-help

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

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-10-27 19:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-13 21:02 Using Go to build a shared library to be called from C LRN
2011-06-14  6:32 ` Ian Lance Taylor
2011-06-14  9:54   ` LRN
2011-06-14 14:02     ` Ian Lance Taylor
2011-10-27 11:24   ` LRN
2011-10-27 19:38     ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).