* 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).