typeconv.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. package zend
  2. // go类型转换为PHP类型
  3. /*
  4. #include <stdlib.h>
  5. #include <zend.h>
  6. #include "../zend/compat.h"
  7. #include "../zend/customize.h"
  8. */
  9. import "C"
  10. import "unsafe"
  11. import (
  12. "log"
  13. "reflect"
  14. )
  15. const (
  16. PHPTY_IS_NULL = C.IS_NULL
  17. PHPTY_IS_LONG = C.IS_LONG
  18. PHPTY_IS_DOUBLE = C.IS_DOUBLE
  19. PHPTY_IS_BOOL = C._IS_BOOL
  20. PHPTY_IS_TRUE = C.IS_TRUE
  21. PHPTY_IS_FALSE = C.IS_FALSE
  22. PHPTY_IS_ARRAY = C.IS_ARRAY
  23. PHPTY_IS_OBJECT = C.IS_OBJECT
  24. PHPTY_IS_STRING = C.IS_STRING
  25. PHPTY_IS_RESOURCE = C.IS_RESOURCE
  26. PHPTY_IS_CONSTANT = C.IS_CONSTANT
  27. PHPTY_IS_CONSTANT_AST = C.IS_CONSTANT_AST
  28. PHPTY_IS_CALLABLE = C.IS_CALLABLE
  29. PHPTY_IS_SELF = C.IS_SELF
  30. PHPTY_IS_INTERFACE = C.IS_ZVAL
  31. PHPTY_IS_CONSTANT_TYPE_MASK = 0x00f
  32. PHPTY_IS_CONSTANT_UNQUALIFIED = 0x010
  33. PHPTY_IS_LEXICAL_VAR = 0x020
  34. PHPTY_IS_LEXICAL_REF = 0x040
  35. PHPTY_IS_CONSTANT_IN_NAMESPACE = 0x100
  36. )
  37. func ArgTypes2Php(fn interface{}) (ptfs *string) {
  38. fty := reflect.TypeOf(fn)
  39. if fty.Kind() != reflect.Func {
  40. log.Panicln("What's that?", fty.Kind().String())
  41. }
  42. var tfs string
  43. for idx := 0; idx < fty.NumIn(); idx++ {
  44. switch fty.In(idx).Kind() {
  45. case reflect.String:
  46. tfs = tfs + "s"
  47. case reflect.Float64:
  48. fallthrough
  49. case reflect.Float32:
  50. tfs = tfs + "d"
  51. case reflect.Bool:
  52. tfs = tfs + "b"
  53. case reflect.Int64:
  54. fallthrough
  55. case reflect.Uint64:
  56. fallthrough
  57. case reflect.Int32:
  58. fallthrough
  59. case reflect.Uint32:
  60. fallthrough
  61. case reflect.Int:
  62. fallthrough
  63. case reflect.Uint:
  64. fallthrough
  65. case reflect.Int16:
  66. fallthrough
  67. case reflect.Uint16:
  68. fallthrough
  69. case reflect.Int8:
  70. fallthrough
  71. case reflect.Uint8:
  72. tfs = tfs + "l"
  73. case reflect.Ptr:
  74. tfs = tfs + "p"
  75. case reflect.Interface:
  76. tfs = tfs + "a" // Any/interface
  77. case reflect.Slice:
  78. tfs = tfs + "v" // vector
  79. case reflect.Map:
  80. tfs = tfs + "m"
  81. default:
  82. log.Panicln("Unsupported kind:", "wtf", fty.In(idx).String(),
  83. fty.In(idx).Kind(), reflect.TypeOf(fn).IsVariadic())
  84. }
  85. }
  86. log.Println("===", tfs, fty.NumIn())
  87. return &tfs
  88. }
  89. func RetType2Php(fn interface{}) (rety int) {
  90. fty := reflect.TypeOf(fn)
  91. if fty.Kind() != reflect.Func {
  92. log.Panicln("What's that?", fty.Kind().String())
  93. }
  94. if fty.NumOut() > 0 {
  95. switch fty.Out(0).Kind() {
  96. case reflect.String:
  97. rety = PHPTY_IS_STRING
  98. case reflect.Float64:
  99. fallthrough
  100. case reflect.Float32:
  101. rety = PHPTY_IS_DOUBLE
  102. case reflect.Bool:
  103. rety = PHPTY_IS_BOOL
  104. case reflect.Int64:
  105. fallthrough
  106. case reflect.Uint64:
  107. fallthrough
  108. case reflect.Int32:
  109. fallthrough
  110. case reflect.Uint32:
  111. fallthrough
  112. case reflect.Int:
  113. fallthrough
  114. case reflect.Uint:
  115. fallthrough
  116. case reflect.Int16:
  117. fallthrough
  118. case reflect.Uint16:
  119. fallthrough
  120. case reflect.Int8:
  121. fallthrough
  122. case reflect.Uint8:
  123. rety = PHPTY_IS_LONG
  124. case reflect.Ptr:
  125. rety = PHPTY_IS_RESOURCE
  126. case reflect.Slice, reflect.Array, reflect.Map:
  127. rety = PHPTY_IS_ARRAY
  128. case reflect.Interface:
  129. // 尝试支持返回interface
  130. rety = PHPTY_IS_INTERFACE
  131. default:
  132. log.Panicln("wtf", fty.Out(0).String(), fty.Out(0).Kind().String())
  133. }
  134. }
  135. return
  136. }
  137. func ArgValuesFromPhp(fn interface{}, args []uintptr) (argv []reflect.Value) {
  138. fty := reflect.TypeOf(fn)
  139. if fty.Kind() != reflect.Func {
  140. log.Panicln("What's that?", fty.Kind().String())
  141. }
  142. argv = make([]reflect.Value, 0)
  143. for idx := 0; idx < fty.NumIn(); idx++ {
  144. switch fty.In(idx).Kind() {
  145. case reflect.String:
  146. var arg = C.GoString((*C.char)(unsafe.Pointer(args[idx])))
  147. var v = reflect.ValueOf(arg).Convert(fty.In(idx))
  148. argv = append(argv, v)
  149. case reflect.Float64:
  150. fallthrough
  151. case reflect.Float32:
  152. var arg = (*C.double)(unsafe.Pointer(args[idx]))
  153. var v = reflect.ValueOf(*arg).Convert(fty.In(idx))
  154. argv = append(argv, v)
  155. C.free(unsafe.Pointer(args[idx]))
  156. case reflect.Bool:
  157. var arg = (C.int)(args[idx])
  158. if arg == 1 {
  159. argv = append(argv, reflect.ValueOf(true))
  160. } else {
  161. argv = append(argv, reflect.ValueOf(false))
  162. }
  163. case reflect.Int64:
  164. fallthrough
  165. case reflect.Uint64:
  166. fallthrough
  167. case reflect.Int32:
  168. fallthrough
  169. case reflect.Uint32:
  170. fallthrough
  171. case reflect.Int:
  172. fallthrough
  173. case reflect.Uint:
  174. fallthrough
  175. case reflect.Int16:
  176. fallthrough
  177. case reflect.Uint16:
  178. fallthrough
  179. case reflect.Int8:
  180. fallthrough
  181. case reflect.Uint8:
  182. var arg = (C.ulonglong)(args[idx])
  183. var v = reflect.ValueOf(arg).Convert(fty.In(idx))
  184. argv = append(argv, v)
  185. case reflect.Ptr:
  186. // 有可能是go类的this指针
  187. if idx == 0 {
  188. // 这里仅是设置一个点位符号,这个gothis指针的位置
  189. argv = append(argv, reflect.ValueOf(0))
  190. } else {
  191. // 不支持其他非this参数的指针
  192. panic("wtf")
  193. }
  194. case reflect.Interface:
  195. log.Println("Unsupported interface kind:",
  196. fty.In(idx).Kind().String(), fty.In(idx).String())
  197. default:
  198. log.Panicln("Unsupported kind:",
  199. fty.In(idx).Kind().String(), fty.In(idx).String())
  200. }
  201. }
  202. if len(argv) != fty.NumIn() {
  203. panic("wtf")
  204. }
  205. return
  206. }
  207. func ArgValuesFromPhp_p(fn interface{}, args []unsafe.Pointer, ismth bool) (argv []reflect.Value) {
  208. fty := reflect.TypeOf(fn)
  209. if fty.Kind() != reflect.Func {
  210. log.Panicln("What's that?", fty.Kind().String())
  211. }
  212. argv = make([]reflect.Value, fty.NumIn())
  213. aidx := 0
  214. for idx := 0; idx < fty.NumIn(); idx++ {
  215. if ismth && idx == 0 {
  216. continue
  217. }
  218. aty := fty.In(idx)
  219. aiv := FROMCIP(args[aidx])
  220. if aiv != nil {
  221. if !reflect.TypeOf(aiv).ConvertibleTo(aty) {
  222. log.Panicln("can't convert ", reflect.TypeOf(aiv).Kind().String(), aty.Kind().String(),
  223. aty.Elem().Kind(), reflect.TypeOf(aiv).AssignableTo(aty), reflect.TypeOf(aiv).Elem().Kind())
  224. }
  225. argv[idx] = reflect.ValueOf(aiv).Convert(aty)
  226. } else {
  227. log.Panicln("nil arg", idx, ismth, fty.Name())
  228. }
  229. aidx += 1
  230. }
  231. if len(argv) != fty.NumIn() {
  232. panic("wtf")
  233. }
  234. return
  235. }
  236. // TODO 多值返回的支持?
  237. func RetValue2Php(fn interface{}, rvs []reflect.Value) (retv uintptr) {
  238. fty := reflect.TypeOf(fn)
  239. if fty.Kind() != reflect.Func {
  240. log.Panicln("What's that?", fty.Kind().String())
  241. }
  242. retv = 0
  243. if fty.NumOut() > 0 {
  244. switch fty.Out(0).Kind() {
  245. case reflect.String:
  246. // 需要reciever 释放内存
  247. retv = uintptr(unsafe.Pointer(C.CString(rvs[0].Interface().(string))))
  248. case reflect.Float64:
  249. fallthrough
  250. case reflect.Float32:
  251. // 需要reciever 释放内存
  252. var pdv *C.double = (*C.double)(C.malloc(8))
  253. *pdv = (C.double)(rvs[0].Interface().(float64))
  254. retv = uintptr(unsafe.Pointer(pdv))
  255. case reflect.Bool:
  256. var bv = rvs[0].Interface().(bool)
  257. if bv {
  258. retv = uintptr(1)
  259. } else {
  260. retv = uintptr(0)
  261. }
  262. case reflect.Int64:
  263. fallthrough
  264. case reflect.Uint64:
  265. fallthrough
  266. case reflect.Int32:
  267. fallthrough
  268. case reflect.Uint32:
  269. fallthrough
  270. case reflect.Int:
  271. fallthrough
  272. case reflect.Uint:
  273. fallthrough
  274. case reflect.Int16:
  275. fallthrough
  276. case reflect.Uint16:
  277. fallthrough
  278. case reflect.Int8:
  279. fallthrough
  280. case reflect.Uint8:
  281. var dty = reflect.TypeOf(uint64(0))
  282. var nv = rvs[0].Convert(dty).Interface().(uint64)
  283. retv = uintptr(nv)
  284. case reflect.Ptr:
  285. var nv = rvs[0].Pointer()
  286. retv = uintptr(nv)
  287. default:
  288. log.Panicln("Unsupported kind:", fty.Out(0).Kind().String())
  289. }
  290. }
  291. return
  292. }
  293. // TODO 多值返回的支持?
  294. func RetValue2Php_p(fn interface{}, rvs []reflect.Value) (retv unsafe.Pointer) {
  295. fty := reflect.TypeOf(fn)
  296. if fty.Kind() != reflect.Func {
  297. log.Panicln("What's that?", fty.Kind().String())
  298. }
  299. if fty.NumOut() > 0 {
  300. rvr := rvs[0].Interface()
  301. return TOCIP(rvr)
  302. }
  303. return nil
  304. }