Skip to content

cmd/cgo: define exported Go func as function #44352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
Closed
2 changes: 2 additions & 0 deletions src/cmd/cgo/gcc.go
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,8 @@ func (p *Package) gccCmd() []string {
c = append(c, "-maix64")
c = append(c, "-mcmodel=large")
}
// disable LTO so we get a real object
c = append(c, "-fno-lto")
c = append(c, "-") //read input from standard input
return c
}
Expand Down
16 changes: 13 additions & 3 deletions src/cmd/cgo/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,18 @@ func (p *Package) writeDefs() {
if *gccgo {
fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
} else {
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
// We must ensure the executable cgo is creating here has a
// reference to all symbols Go code is referring
// to -- because otherwise the system linker might decline
// to add DT_NEEDED entries for the library that has the symbol definition.
// We treat function pointer types differently to avoid link-time failures
// when using LTO with an external linker.
if n.Kind == "fpvar" {
fmt.Fprintf(fm, "extern void %s();\n", n.C)
} else {
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
}
fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
Expand Down Expand Up @@ -1028,7 +1038,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a *%s) {\n", cPrefix, exp.ExpName, gotype)

fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
fmt.Fprintf(fm, "void _cgoexp%s_%s(void* p){}\n", cPrefix, exp.ExpName)

if gccResult != "void" {
// Write results back to frame.
Expand Down
38 changes: 38 additions & 0 deletions src/cmd/go/testdata/script/issue_43830.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# tests golang.org/issue/43830

[!cgo] skip 'skipping test without cgo'
[!exec:gcc] skip 'skipping test without gcc present'
[openbsd] env CC='clang'
[!openbsd] env CC='gcc'

env CGO_CFLAGS='-Wno-ignored-optimization-argument -flto -ffat-lto-objects'

go build main.go add.go

-- main.go --

package main

/*
int c_add(int a, int b) {
return myadd(a, b);
}
*/
import "C"

func main() {
println(C.c_add(1, 2))
}

-- add.go --

package main

import "C"

/* test */

//export myadd
func myadd(a C.int, b C.int) C.int {
return a + b
}
32 changes: 32 additions & 0 deletions src/cmd/go/testdata/script/issue_43830_2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# tests golang.org/issue/43830

[!cgo] skip 'skipping test without cgo'
[!exec:gcc] skip 'skipping test without gcc present'
[openbsd] env CC='clang'
[!openbsd] env CC='gcc'

env CGO_CFLAGS='-Wno-ignored-optimization-argument -flto -ffat-lto-objects'

go build main.go

-- main.go --

package main

import "fmt"

// #include "hello.h"
import "C"

func main() {
hello := C.hello
fmt.Printf("%v\n", hello)
}

-- hello.h --

#include <stdio.h>

void hello(void) {
printf("hello\n");
}