Commit 12e7ce95 authored by Ian Lance Taylor's avatar Ian Lance Taylor

Add //export to cgo.

The new //export comment marks a Go function as callable from
C.  The syntax is "//export NAME" where NAME is the name of
the function as seen from C.  If such a comment is seen, cgo
will generate two new files: _cgo_export.h and _cgo_export.c.
The _cgo_export.h file provides declarations which C code may
use to call Go functions.  The _cgo_export.c file contains
wrappers, and is to be compiled with gcc.

The changes to Make.pkg support using this from a Go Makefile,
though it could probably be more convenient.

R=rsc
CC=golang-dev
https://golang.org/cl/853042
parent 2e20386f
......@@ -44,7 +44,7 @@ coverage:
$(QUOTED_GOBIN)/gotest
$(QUOTED_GOBIN)/6cov -g $(shell pwd) $O.out | grep -v '_test\.go:'
CLEANFILES+=*.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go *.so _obj _test _testmain.go
CLEANFILES+=*.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* *.so _obj _test _testmain.go
test:
$(QUOTED_GOBIN)/gotest
......@@ -92,9 +92,10 @@ dir:
#
# to the main Makefile. This signals that cgo should process x.go
# and y.go when building the package.
# There are two optional variables to set, CGO_CFLAGS and CGO_LDFLAGS,
# which specify compiler and linker flags to use when compiling
# (using gcc) the C support for x.go and y.go.
# There are three optional variables to set, CGO_CFLAGS, CGO_LDFLAGS,
# and CGO_DEPS, which specify compiler flags, linker flags, and linker
# dependencies to use when compiling (using gcc) the C support for
# x.go and y.go.
# Cgo translates each x.go file listed in $(CGOFILES) into a basic
# translation of x.go, called x.cgo1.go. Additionally, three other
......@@ -118,6 +119,9 @@ _cgo_defun.c _cgo_gotypes.go: $(CGOFILES)
%.cgo2.o: %.cgo2.c
gcc $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) $*.cgo2.c
_cgo_export.o: _cgo_export.c _cgo_export.h
gcc $(_CGO_CFLAGS_$(GOARCH)) -fPIC -O2 -o $@ -c $(CGO_CFLAGS) _cgo_export.c
# The rules above added x.cgo1.go and _cgo_gotypes.go to $(GOFILES),
# added _cgo_defun.$O to $OFILES, and added the installed copy of
# package_x.so (built from x.cgo2.c) to $(INSTALLFILES).
......@@ -139,7 +143,7 @@ _CGO_LDFLAGS_darwin=-dynamiclib -Wl,-undefined,dynamic_lookup
_cgo_defun.$O: _cgo_defun.c
$(QUOTED_GOBIN)/$(CC) $(CFLAGS) $(RUNTIME_CFLAGS) _cgo_defun.c
_cgo_.so: $(GCC_OFILES)
_cgo_.so: $(GCC_OFILES) $(CGO_DEPS)
gcc $(_CGO_CFLAGS_$(GOARCH)) -o $@ $(GCC_OFILES) $(CGO_LDFLAGS) $(_CGO_LDFLAGS_$(GOOS))
$(pkgdir)/$(TARG).so: _cgo_.so
......
......@@ -13,6 +13,7 @@ import (
"go/parser"
"go/scanner"
"os"
"strings"
)
// A Cref refers to an expression of the form C.xxx in the AST.
......@@ -25,6 +26,12 @@ type Cref struct {
FuncType *FuncType
}
// A ExpFunc is an exported function, callable from C.
type ExpFunc struct {
Func *ast.FuncDecl
ExpName string // name to use from C
}
// A Prog collects information about a cgo program.
type Prog struct {
AST *ast.File // parsed AST
......@@ -37,6 +44,7 @@ type Prog struct {
Funcdef map[string]*FuncType
Enumdef map[string]int64
Constdef map[string]string
ExpFuncs []*ExpFunc
PtrSize int64
GccOptions []string
OutDefs map[string]bool
......@@ -303,6 +311,8 @@ func walk(x interface{}, p *Prog, context string) {
walk(n.Body, p, "stmt")
}
checkExpFunc(n, p)
case *ast.File:
walk(n.Decls, p, "decl")
......@@ -329,3 +339,38 @@ func walk(x interface{}, p *Prog, context string) {
}
}
}
// If a function should be exported add it to ExpFuncs.
func checkExpFunc(n *ast.FuncDecl, p *Prog) {
if n.Doc == nil {
return
}
for _, c := range n.Doc.List {
if string(c.Text[0:9]) != "//export " {
continue
}
name := strings.TrimSpace(string(c.Text[9:]))
if name == "" {
error(c.Position, "export missing name")
}
if p.ExpFuncs == nil {
p.ExpFuncs = make([]*ExpFunc, 0, 8)
}
i := len(p.ExpFuncs)
if i >= cap(p.ExpFuncs) {
new := make([]*ExpFunc, 2*i)
for j, v := range p.ExpFuncs {
new[j] = v
}
p.ExpFuncs = new
}
p.ExpFuncs = p.ExpFuncs[0 : i+1]
p.ExpFuncs[i] = &ExpFunc{
Func: n,
ExpName: name,
}
break
}
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment