forked from qiniu/py
/
goregister.go
78 lines (62 loc) · 1.92 KB
/
goregister.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
package py
import "reflect"
import "strings"
import "github.com/qiniu/log"
// ------------------------------------------------------------------------------------------
// Note: Methods take the receiver as the first argument, which the want
// signature doesn't include.
func sigMatches(got, want reflect.Type) bool {
nin := want.NumIn()
if got.NumIn()-1 != nin {
return false
}
nout := want.NumOut()
if got.NumOut() != nout {
return false
}
for i := 0; i < nin; i++ {
if got.In(i+1) != want.In(i) {
return false
}
}
for i := 0; i < nout; i++ {
if got.Out(i) != want.Out(i) {
return false
}
}
return true
}
// ------------------------------------------------------------------------------------------
var typUnaryFunc = reflect.TypeOf(func() (*Base, error)(nil))
var typBinaryCallFunc = reflect.TypeOf(func(*Tuple) (*Base, error)(nil))
var typTernaryCallFunc = reflect.TypeOf(func(*Tuple, *Dict) (*Base, error)(nil))
type RegisterCtx []*Closure // 只是让对象不被gc
func Register(dict *Dict, nsprefix string, self interface{}) (ctx RegisterCtx) {
typ := reflect.TypeOf(self)
selfv := reflect.ValueOf(self)
nmethod := typ.NumMethod()
for i := 0; i < nmethod; i++ {
method := typ.Method(i)
mtype := method.Type
mname := method.Name
if mtype.PkgPath() != "" || !strings.HasPrefix(mname, "Py_") {
continue
}
nin := mtype.NumIn()
name := mname[3:]
fullname := nsprefix + name
if nin == 3 && sigMatches(mtype, typTernaryCallFunc) || nin == 2 && sigMatches(mtype, typBinaryCallFunc) {
closure := &Closure{selfv, method.Func}
f := closure.NewFunction(fullname, nin, "")
dict.SetItemString(name, f)
f.Decref()
ctx = append(ctx, closure)
log.Debug("Register", fullname)
} else {
log.Warnf("Invalid signature of method %s, register failed", fullname)
continue
}
}
return
}
// ------------------------------------------------------------------------------------------