forked from gefarion/python2go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathc.go
115 lines (96 loc) · 1.87 KB
/
c.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main
/*
#include <stdlib.h>
typedef struct{
int n;
char *s;
}SrvObj;
static inline int callSrvObjCallback(void *f, SrvObj *a, SrvObj *b) {
return ((int (*)(SrvObj*, SrvObj*))f)(a, b);
}
*/
import "C"
import (
"encoding/json"
"errors"
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"sync"
"syscall"
"unsafe"
)
type Srv struct {
cb unsafe.Pointer
}
type Msg struct {
Number int `json:"n"`
String string `json:"s"`
}
type Cache struct {
req, resp Msg
cReq, cResp C.SrvObj
}
var cachePool sync.Pool
func (s *Srv) reqHandler(w http.ResponseWriter, r *http.Request) {
var b []byte = nil
var err error
if r.Method != "POST" {
http.Error(w, "only POST supporte", http.StatusMethodNotAllowed)
return
}
cv := cachePool.Get()
if cv == nil {
cv = &Cache{}
}
c := cv.(*Cache)
defer cachePool.Put(c)
defer r.Body.Close()
err = json.NewDecoder(r.Body).Decode(&c.req)
if err != nil {
goto Error
}
c.cReq = C.SrvObj{
n: C.int(c.req.Number),
s: C.CString(c.req.String),
}
defer C.free(unsafe.Pointer(c.cReq.s))
if C.callSrvObjCallback(s.cb, &c.cReq, &c.cResp) != 0 {
err = errors.New("callSrvObjCallback: failed")
goto Error
}
c.resp = Msg{Number: int(c.cResp.n), String: C.GoString(c.cResp.s)}
b, err = json.Marshal(c.resp)
if err != nil {
goto Error
}
w.Write(b)
return
Error:
http.Error(w, err.Error(), http.StatusInternalServerError)
}
func (s *Srv) ListenAndServe(addr string) error {
http.HandleFunc("/req", s.reqHandler)
return http.ListenAndServe(addr, nil)
}
var once sync.Once
func doSignals() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
fmt.Println(sig)
os.Exit(0)
}()
}
//export Serve
func Serve(addr string, callback unsafe.Pointer) {
flag.Parse()
once.Do(doSignals)
s := &Srv{cb: callback}
log.Fatal(s.ListenAndServe(addr))
}
func main() {}