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