mirror of https://github.com/go-python/gopy.git
gopy-gen: first import
This commit is contained in:
commit
9d0889d184
|
@ -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.
|
|
@ -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
|
||||
|
||||
```
|
|
@ -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
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
Loading…
Reference in New Issue