123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- package zend
- // go类型转换为PHP类型
- /*
- #include <stdlib.h>
- #include <zend.h>
- #include "../zend/compat.h"
- #include "../zend/customize.h"
- */
- import "C"
- import "unsafe"
- import (
- "log"
- "reflect"
- )
- const (
- PHPTY_IS_NULL = C.IS_NULL
- PHPTY_IS_LONG = C.IS_LONG
- PHPTY_IS_DOUBLE = C.IS_DOUBLE
- PHPTY_IS_BOOL = C._IS_BOOL
- PHPTY_IS_TRUE = C.IS_TRUE
- PHPTY_IS_FALSE = C.IS_FALSE
- PHPTY_IS_ARRAY = C.IS_ARRAY
- PHPTY_IS_OBJECT = C.IS_OBJECT
- PHPTY_IS_STRING = C.IS_STRING
- PHPTY_IS_RESOURCE = C.IS_RESOURCE
- PHPTY_IS_CONSTANT = C.IS_CONSTANT
- PHPTY_IS_CONSTANT_AST = C.IS_CONSTANT_AST
- PHPTY_IS_CALLABLE = C.IS_CALLABLE
- PHPTY_IS_SELF = C.IS_SELF
- PHPTY_IS_INTERFACE = C.IS_ZVAL
- PHPTY_IS_CONSTANT_TYPE_MASK = 0x00f
- PHPTY_IS_CONSTANT_UNQUALIFIED = 0x010
- PHPTY_IS_LEXICAL_VAR = 0x020
- PHPTY_IS_LEXICAL_REF = 0x040
- PHPTY_IS_CONSTANT_IN_NAMESPACE = 0x100
- )
- func ArgTypes2Php(fn interface{}) (ptfs *string) {
- fty := reflect.TypeOf(fn)
- if fty.Kind() != reflect.Func {
- log.Panicln("What's that?", fty.Kind().String())
- }
- var tfs string
- for idx := 0; idx < fty.NumIn(); idx++ {
- switch fty.In(idx).Kind() {
- case reflect.String:
- tfs = tfs + "s"
- case reflect.Float64:
- fallthrough
- case reflect.Float32:
- tfs = tfs + "d"
- case reflect.Bool:
- tfs = tfs + "b"
- case reflect.Int64:
- fallthrough
- case reflect.Uint64:
- fallthrough
- case reflect.Int32:
- fallthrough
- case reflect.Uint32:
- fallthrough
- case reflect.Int:
- fallthrough
- case reflect.Uint:
- fallthrough
- case reflect.Int16:
- fallthrough
- case reflect.Uint16:
- fallthrough
- case reflect.Int8:
- fallthrough
- case reflect.Uint8:
- tfs = tfs + "l"
- case reflect.Ptr:
- tfs = tfs + "p"
- case reflect.Interface:
- tfs = tfs + "a" // Any/interface
- case reflect.Slice:
- tfs = tfs + "v" // vector
- case reflect.Map:
- tfs = tfs + "m"
- default:
- log.Panicln("Unsupported kind:", "wtf", fty.In(idx).String(),
- fty.In(idx).Kind(), reflect.TypeOf(fn).IsVariadic())
- }
- }
- log.Println("===", tfs, fty.NumIn())
- return &tfs
- }
- func RetType2Php(fn interface{}) (rety int) {
- fty := reflect.TypeOf(fn)
- if fty.Kind() != reflect.Func {
- log.Panicln("What's that?", fty.Kind().String())
- }
- if fty.NumOut() > 0 {
- switch fty.Out(0).Kind() {
- case reflect.String:
- rety = PHPTY_IS_STRING
- case reflect.Float64:
- fallthrough
- case reflect.Float32:
- rety = PHPTY_IS_DOUBLE
- case reflect.Bool:
- rety = PHPTY_IS_BOOL
- case reflect.Int64:
- fallthrough
- case reflect.Uint64:
- fallthrough
- case reflect.Int32:
- fallthrough
- case reflect.Uint32:
- fallthrough
- case reflect.Int:
- fallthrough
- case reflect.Uint:
- fallthrough
- case reflect.Int16:
- fallthrough
- case reflect.Uint16:
- fallthrough
- case reflect.Int8:
- fallthrough
- case reflect.Uint8:
- rety = PHPTY_IS_LONG
- case reflect.Ptr:
- rety = PHPTY_IS_RESOURCE
- case reflect.Slice, reflect.Array, reflect.Map:
- rety = PHPTY_IS_ARRAY
- case reflect.Interface:
- // 尝试支持返回interface
- rety = PHPTY_IS_INTERFACE
- default:
- log.Panicln("wtf", fty.Out(0).String(), fty.Out(0).Kind().String())
- }
- }
- return
- }
- func ArgValuesFromPhp(fn interface{}, args []uintptr) (argv []reflect.Value) {
- fty := reflect.TypeOf(fn)
- if fty.Kind() != reflect.Func {
- log.Panicln("What's that?", fty.Kind().String())
- }
- argv = make([]reflect.Value, 0)
- for idx := 0; idx < fty.NumIn(); idx++ {
- switch fty.In(idx).Kind() {
- case reflect.String:
- var arg = C.GoString((*C.char)(unsafe.Pointer(args[idx])))
- var v = reflect.ValueOf(arg).Convert(fty.In(idx))
- argv = append(argv, v)
- case reflect.Float64:
- fallthrough
- case reflect.Float32:
- var arg = (*C.double)(unsafe.Pointer(args[idx]))
- var v = reflect.ValueOf(*arg).Convert(fty.In(idx))
- argv = append(argv, v)
- C.free(unsafe.Pointer(args[idx]))
- case reflect.Bool:
- var arg = (C.int)(args[idx])
- if arg == 1 {
- argv = append(argv, reflect.ValueOf(true))
- } else {
- argv = append(argv, reflect.ValueOf(false))
- }
- case reflect.Int64:
- fallthrough
- case reflect.Uint64:
- fallthrough
- case reflect.Int32:
- fallthrough
- case reflect.Uint32:
- fallthrough
- case reflect.Int:
- fallthrough
- case reflect.Uint:
- fallthrough
- case reflect.Int16:
- fallthrough
- case reflect.Uint16:
- fallthrough
- case reflect.Int8:
- fallthrough
- case reflect.Uint8:
- var arg = (C.ulonglong)(args[idx])
- var v = reflect.ValueOf(arg).Convert(fty.In(idx))
- argv = append(argv, v)
- case reflect.Ptr:
- // 有可能是go类的this指针
- if idx == 0 {
- // 这里仅是设置一个点位符号,这个gothis指针的位置
- argv = append(argv, reflect.ValueOf(0))
- } else {
- // 不支持其他非this参数的指针
- panic("wtf")
- }
- case reflect.Interface:
- log.Println("Unsupported interface kind:",
- fty.In(idx).Kind().String(), fty.In(idx).String())
- default:
- log.Panicln("Unsupported kind:",
- fty.In(idx).Kind().String(), fty.In(idx).String())
- }
- }
- if len(argv) != fty.NumIn() {
- panic("wtf")
- }
- return
- }
- func ArgValuesFromPhp_p(fn interface{}, args []unsafe.Pointer, ismth bool) (argv []reflect.Value) {
- fty := reflect.TypeOf(fn)
- if fty.Kind() != reflect.Func {
- log.Panicln("What's that?", fty.Kind().String())
- }
- argv = make([]reflect.Value, fty.NumIn())
- aidx := 0
- for idx := 0; idx < fty.NumIn(); idx++ {
- if ismth && idx == 0 {
- continue
- }
- aty := fty.In(idx)
- aiv := FROMCIP(args[aidx])
- if aiv != nil {
- if !reflect.TypeOf(aiv).ConvertibleTo(aty) {
- log.Panicln("can't convert ", reflect.TypeOf(aiv).Kind().String(), aty.Kind().String(),
- aty.Elem().Kind(), reflect.TypeOf(aiv).AssignableTo(aty), reflect.TypeOf(aiv).Elem().Kind())
- }
- argv[idx] = reflect.ValueOf(aiv).Convert(aty)
- } else {
- log.Panicln("nil arg", idx, ismth, fty.Name())
- }
- aidx += 1
- }
- if len(argv) != fty.NumIn() {
- panic("wtf")
- }
- return
- }
- // TODO 多值返回的支持?
- func RetValue2Php(fn interface{}, rvs []reflect.Value) (retv uintptr) {
- fty := reflect.TypeOf(fn)
- if fty.Kind() != reflect.Func {
- log.Panicln("What's that?", fty.Kind().String())
- }
- retv = 0
- if fty.NumOut() > 0 {
- switch fty.Out(0).Kind() {
- case reflect.String:
- // 需要reciever 释放内存
- retv = uintptr(unsafe.Pointer(C.CString(rvs[0].Interface().(string))))
- case reflect.Float64:
- fallthrough
- case reflect.Float32:
- // 需要reciever 释放内存
- var pdv *C.double = (*C.double)(C.malloc(8))
- *pdv = (C.double)(rvs[0].Interface().(float64))
- retv = uintptr(unsafe.Pointer(pdv))
- case reflect.Bool:
- var bv = rvs[0].Interface().(bool)
- if bv {
- retv = uintptr(1)
- } else {
- retv = uintptr(0)
- }
- case reflect.Int64:
- fallthrough
- case reflect.Uint64:
- fallthrough
- case reflect.Int32:
- fallthrough
- case reflect.Uint32:
- fallthrough
- case reflect.Int:
- fallthrough
- case reflect.Uint:
- fallthrough
- case reflect.Int16:
- fallthrough
- case reflect.Uint16:
- fallthrough
- case reflect.Int8:
- fallthrough
- case reflect.Uint8:
- var dty = reflect.TypeOf(uint64(0))
- var nv = rvs[0].Convert(dty).Interface().(uint64)
- retv = uintptr(nv)
- case reflect.Ptr:
- var nv = rvs[0].Pointer()
- retv = uintptr(nv)
- default:
- log.Panicln("Unsupported kind:", fty.Out(0).Kind().String())
- }
- }
- return
- }
- // TODO 多值返回的支持?
- func RetValue2Php_p(fn interface{}, rvs []reflect.Value) (retv unsafe.Pointer) {
- fty := reflect.TypeOf(fn)
- if fty.Kind() != reflect.Func {
- log.Panicln("What's that?", fty.Kind().String())
- }
- if fty.NumOut() > 0 {
- rvr := rvs[0].Interface()
- return TOCIP(rvr)
- }
- return nil
- }
|