Skip to content

Commit

Permalink
Import from bitbucket
Browse files Browse the repository at this point in the history
  • Loading branch information
tebeka committed Nov 8, 2016
1 parent f5ef251 commit 1e431e2
Show file tree
Hide file tree
Showing 46 changed files with 21,349 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import-c-go-il/callback/callback
pandas-pyweb-il/56*.csv
pandas-pyweb-il/screen.m*
python-logging/data
python-logging/kibana-latest/
python-logging/logstash*.jar
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Various talks given by [Miki](mailto:[email protected])
8 changes: 8 additions & 0 deletions import-c-go-il/callback/callback.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <stdio.h>
#include "_cgo_export.h"

void
c_func() {
printf("Calling Go\n");
go_func();
}
16 changes: 16 additions & 0 deletions import-c-go-il/callback/callback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import "fmt"

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

//export go_func
func go_func() {
fmt.Println("Hello from Go")
}

func main() {
C.c_func();
}

6 changes: 6 additions & 0 deletions import-c-go-il/callback/callback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef CALLBACK_H
#define CALLBACK_H

void c_func();

#endif
17 changes: 17 additions & 0 deletions import-c-go-il/err.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

// #include <math.h>
// #cgo LDFLAGS: -lm
import "C"

import (
"fmt"
)

func main() {
i, err := C.sqrt(-1)
if err != nil {
fmt.Printf("error: %s\n", err) // Go will use strerror for message
}
fmt.Printf("i = %v\n", i)
}
125 changes: 125 additions & 0 deletions import-c-go-il/import-c.slide
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import "C"
Calling C From Go
19 Mar 2015
Tags: go c

Miki Tebeka
CEO, 353solutions
miki@353solution
http://353solutions.com
@tebeka

* Why C?

After all we have Go, which is much better :)

However, there is a *huge* volume of software written in C.
We'd like to re-use it and not re-write it.

* import "C" (A.K.A cgo)

Provides an easy bridge between Go and C

The Downside
- Hard to find docs (see reference slide)
- Pay attention to memory leaks
- Compilation time grows
- For C++ you need `extern`"C"` and C like wrapper
- Users need C compilers and libraries installed

Note that are other options (such as [[http://www.swig.org/][swig]])



* Minimal Example

.play sqrt.go


* Strings

.play str.go

* Ahhhhhh!

.image picard1.jpg 400 600

* Strings

.play str2.go

* But ...

.image picard2.jpg 400 600

* Strings

.play str3.go

* Structs

.play struct.go

* Calling Go from C

`callback.c`

.code -numbers callback/callback.c

`callback.h`

.code -numbers callback/callback.h

* Calling Go from C

`callback.go`

.code -numbers callback/callback.go

* Go Style Errors

.play err.go

* Case Study - snowball

- [[https://bitbucket.org/tebeka/snowball]]
- Port of [[http://snowball.tartarus.org/][snowball]] stemmer to Go
- Had to flatten directories and rewrite #include
- Wasn't that painful

.play stem.go

* snowball - imports and definition

.code -numbers snowball.go /START_IMPORT/,/END_IMPORT/

* snowball - New and free

.code -numbers snowball.go /START_NEW/,/END_NEW/


* snowball - Stem

snowball uses `sb_symbol*` for string

.code -numbers snowball.go /START_STEM/,/END_STEM/

* snowball - List

The list of languages is a `static`char*` array with a `NULL` sentinal

.code -numbers snowball.go /START_LIST/,/END_LIST/


* References

- [[http://golang.org/cmd/cgo/][cgo docs]]
- [[http://golang.org/doc/articles/c_go_cgo.html][C? Go? Cgo!]]
- [[http://golang.org/misc/cgo/][cgo examples]]
- [[https://github.com/golang/go/wiki/cgo][cgo wiki]]
- [[http://stackoverflow.com/search?q=%5Bgo%5D+cgo][StackOverflow]]

* Now Go Hack!

.image real-programmers.jpg 400 600

Binary file added import-c-go-il/picard1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added import-c-go-il/picard2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added import-c-go-il/real-programmers.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
98 changes: 98 additions & 0 deletions import-c-go-il/snowball.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// snowball stemmer
//
// Example:
// stemmer = snowball.New("english")
// fmt.Println(stemmer.stem("running")) // Will print "run"
package snowball

// START_IMPORT OMIT
import (
"fmt"
"runtime"
"unsafe"
)
/*
#include <stdlib.h>
#include "libstemmer.h"
*/
import "C"


// Stemmer structure
type Stemmer struct {
lang string
stmr *C.struct_sb_stemmer
}

// END_IMPORT OMIT

const (
Version = "0.1.2"
)

// START_NEW OMIT
// New creates a new stemmer for lang
func New(lang string) (*Stemmer, error) {
stmr := &Stemmer{
lang,
C.sb_stemmer_new(C.CString(lang), nil),
}

if stmr.stmr == nil {
return nil, fmt.Errorf("can't create stemmer for lang %s", lang)
}

runtime.SetFinalizer(stmr, free) // Free C memory when GCed

return stmr, nil
}

// free C resources
func free(stmr *Stemmer) {
if stmr.stmr != nil {
C.sb_stemmer_delete(stmr.stmr)
stmr.stmr = nil
}
}
// END_NEW OMIT

// Lang return the stemmer language
func (stmr *Stemmer) Lang() string {
return stmr.lang
}

// START_STEM OMIT
// Stem returns them stem of word (e.g. running -> run)
func (stmr *Stemmer) Stem(word string) string {
ptr := unsafe.Pointer(C.CString(word))
defer C.free(ptr)

w := (*C.sb_symbol)(ptr)
res := unsafe.Pointer(C.sb_stemmer_stem(stmr.stmr, w, C.int(len(word))))
size := C.sb_stemmer_length(stmr.stmr)

buf := C.GoBytes(res, size)
return string(buf)
}
// END_STEM OMIT

// START_LIST OMIT
// List returns the list of languages supported by snowball
func List() []string {
names := []string{}

// We don't need to free since sb_stemmer_list return pointer to static variable
cp := uintptr(unsafe.Pointer(C.sb_stemmer_list()))
size := unsafe.Sizeof(uintptr(0))

for {
name := C.GoString(*(**C.char)(unsafe.Pointer(cp)))
if len(name) == 0 {
break
}
names = append(names, name)
cp += size
}
return names
}
// END_LIST OMIT
14 changes: 14 additions & 0 deletions import-c-go-il/sqrt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

import "fmt"

// #include <math.h>
// #cgo LDFLAGS: -lm
import "C"


func main() {
v := 16.0
s := C.sqrt(C.double(v))
fmt.Printf("sqrt(%f) = %f\n", v, s)
}
15 changes: 15 additions & 0 deletions import-c-go-il/stem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"fmt"
"bitbucket.org/tebeka/snowball"
)

func main() {
stemmer, _ := snowball.New("english") // Error ignored for brevity

word := "running"
stem := stemmer.Stem(word)
fmt.Printf("%s -> %s\n", word, stem)
}

15 changes: 15 additions & 0 deletions import-c-go-il/str.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

// #include <string.h>
import "C"

import (
"fmt"
)

func main() {
str := "Gophers Rock!"
dup := C.strdup(C.CString(str))
fmt.Printf("dup: %s\n", dup)
}

17 changes: 17 additions & 0 deletions import-c-go-il/str2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

// #include <string.h>
// #include <stdlib.h>
import "C"

import (
"fmt"
)

func main() {
str := "Gophers Rock!"
dup := C.strdup(C.CString(str))

gostr := C.GoString(dup)
fmt.Println(gostr)
}
23 changes: 23 additions & 0 deletions import-c-go-il/str3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

// #include <string.h>
// #include <stdlib.h>
import "C"
import "fmt"
import "unsafe"

func free(cstr *C.char) {
C.free(unsafe.Pointer(cstr))
}

func main() {
str := "Gophers Rock!"
cstr:= C.CString(str)
defer free(cstr)

dup := C.strdup(C.CString(str))
defer free(dup)

gostr := C.GoString(dup)
fmt.Println(gostr)
}
23 changes: 23 additions & 0 deletions import-c-go-il/struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

// meanwhile at stdlib.h:
// typedef struct
// {
// int quot; /* Quotient. */
// int rem; /* Remainder. */
// } div_t;

// #include <stdlib.h>
import "C"
import "fmt"

func main() {
var dt C.div_t // Look Ma! C types

dt = C.div(16, 6)
fmt.Printf("quot: %d, rem: %d\n", dt.quot, dt.rem)

dt.quot = 17 // Mutate the struct
fmt.Printf("%v\n", dt) // %v works as well
}

Loading

0 comments on commit 1e431e2

Please sign in to comment.