gopy-gen: first import

This commit is contained in:
Sebastien Binet 2015-01-30 18:01:15 +01:00
commit 9d0889d184
5 changed files with 343 additions and 0 deletions

23
LICENSE Normal file
View File

@ -0,0 +1,23 @@
Copyright ©2015 The go-python Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the gonum project nor the names of its authors and
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

92
README.md Normal file
View File

@ -0,0 +1,92 @@
gopy-gen
========
`gopy-gen` generates a `CPython` extension module from a `go` package.
## Installation
```sh
$ go get github.com/go-python/gopy-gen
```
## Documentation
Documentation is available on [godoc](https://godoc.org):
https://godoc.org/github.com/go-python/gopy-gen
or directly from the command-line prompt:
```sh
$ gopy-gen -help
gopy-gen generates Python language bindings for Go.
Usage:
$ gopy-gen [options] <go-package-name>
For usage details, see godoc:
$ godoc github.com/go-python/gopy-gen
-lang="python": target language for bindings
-odir="": output directory for bindings
```
## Examples
```sh
$ gopy-gen -lang=python github.com/go-python/gopy-gen/_examples/hi
$ gopy-gen -lang=go github.com/go-python/gopy-gen/_examples/hi
```
Have also a look at [_examples/py_hi/gen.go](_examples/py_hi/gen.go):
`gopy-gen` can be used via `go generate`.
Running `go generate` in `_examples/py_hi/gen.go` will generate `hi.c`
and `hi.go`.
The `py_hi` package can then be used and imported from a
`go-python`-based `main`.
See [_examples/gopy-test](_examples/gopy-test):
```go
// a go wrapper around py-main
package main
import (
"os"
"github.com/go-python/gopy-gen/_examples/py_hi"
python "github.com/sbinet/go-python"
)
func init() {
err := python.Initialize()
if err != nil {
panic(err.Error())
}
py_hi.Import()
}
func main() {
rc := python.Py_Main(os.Args)
os.Exit(rc)
}
```
running `gopy-test`:
```python
>>> import hi
>>> hi.Add(1,2)
3
>>> hi.Hi()
hi from go
>>> hi.Hello("you")
hello you from go
```

26
doc.go Normal file
View File

@ -0,0 +1,26 @@
// Copyright 2015 The go-python Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
gopy-gen generates language bindings that make it possible to call Go code
and pass objects from Java.
Using gopy-gen
gopy-gen takes a Go package and generates bindings for all of the exported
symbols. The exported symbols define the cross-language interface.
The gopy-gen tool generates both an API stub in Python, and binding code in
Go. Start with a Go package:
package hi
import "fmt"
func Hello(name string) {
fmt.Println("Hello, %s!\n", name)
}
*/
package main

114
gen.go Normal file
View File

@ -0,0 +1,114 @@
// Copyright 2015 The go-python Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"go/ast"
"go/build"
"go/parser"
"go/scanner"
"go/token"
"os"
"path/filepath"
"github.com/go-python/py/bind"
"golang.org/x/tools/go/loader"
)
var (
fset = token.NewFileSet()
)
func genPkg(odir string, pkg *build.Package) error {
var err error
var o *os.File
files, err := parseFiles(pkg.Dir, pkg.GoFiles)
if err != nil {
return err
}
conf := loader.Config{
SourceImports: true,
Fset: fset,
}
conf.TypeChecker.Error = func(e error) {
errorf("%v\n", e)
err = e
}
conf.CreateFromFiles(pkg.ImportPath, files...)
program, err := conf.Load()
if err != nil {
errorf("%v\n", err)
return err
}
p := program.Created[0].Pkg
switch *lang {
case "python", "py":
o, err = os.Create(filepath.Join(odir, p.Name()+".c"))
if err != nil {
return err
}
err = bind.GenCPython(o, fset, p)
case "go":
o, err = os.Create(filepath.Join(odir, p.Name()+".go"))
if err != nil {
return err
}
err = bind.GenGo(o, fset, p)
default:
return fmt.Errorf("unknown target language: %q\n", *lang)
}
if err != nil {
if list, _ := err.(bind.ErrorList); len(list) > 0 {
for _, err := range list {
errorf("%v\n", err)
}
} else {
errorf("%v\n", err)
}
}
if err != nil {
return err
}
err = o.Close()
if err != nil {
return err
}
return err
}
func parseFiles(dir string, fnames []string) ([]*ast.File, error) {
var (
files []*ast.File
err error
)
for _, fname := range fnames {
path := filepath.Join(dir, fname)
file, errf := parser.ParseFile(fset, path, nil, parser.AllErrors)
if errf != nil {
err = errf
if list, _ := err.(scanner.ErrorList); len(list) > 0 {
for _, err := range list {
errorf("%v\n", err)
}
} else {
errorf("%v\n", err)
}
}
files = append(files, file)
}
return files, err
}

88
main.go Normal file
View File

@ -0,0 +1,88 @@
// Copyright 2015 The go-python Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"flag"
"fmt"
"go/build"
"log"
"os"
"path/filepath"
)
var (
lang = flag.String("lang", "python", "target language for bindings")
odir = flag.String("odir", "", "output directory for bindings")
//pkg = flag.String("pkg", "", "package name of the bindings")
usage = `gopy-gen generates Python language bindings for Go.
Usage:
$ gopy-gen [options] <go-package-name>
For usage details, see godoc:
$ godoc github.com/go-python/gopy-gen
`
)
func errorf(format string, args ...interface{}) (int, error) {
return fmt.Fprintf(os.Stderr, format, args...)
}
func main() {
var err error
flag.Usage = func() {
fmt.Fprintf(os.Stderr, usage)
flag.PrintDefaults()
}
flag.Parse()
if flag.NArg() != 1 {
log.Printf("expect a fully qualified go package name as argument\n")
flag.Usage()
os.Exit(1)
}
cwd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
if *odir == "" {
*odir = cwd
} else {
err = os.MkdirAll(*odir, 0755)
if err != nil {
log.Printf("could not create output directory: %v\n", err)
os.Exit(1)
}
}
*odir, err = filepath.Abs(*odir)
if err != nil {
log.Printf("could not infer absolute path to output directory: %v\n", err)
os.Exit(1)
}
path := flag.Arg(0)
pkg, err := build.Import(path, cwd, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", path, err)
os.Exit(1)
}
err = genPkg(*odir, pkg)
if err != nil {
log.Fatal(err)
}
os.Exit(0)
}