makefunc_ffi.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package reflect
  5. import (
  6. "unsafe"
  7. )
  8. // The makeFuncFFI function, written in C, fills in an FFI closure.
  9. // It arranges for ffiCall to be invoked directly from FFI.
  10. func makeFuncFFI(ftyp *funcType, impl unsafe.Pointer)
  11. // FFICallbackGo implements the Go side of the libffi callback.
  12. // It is exported so that C code can call it.
  13. //
  14. // The call chain arriving here looks like
  15. // some_go_caller
  16. // ->some_ffi_internals
  17. // ->ffi_callback (in C)
  18. // ->FFICallbackGo
  19. //
  20. // The ffi_callback handles __go_makefunc_can_recover, and
  21. // then passes off the data as received from ffi here.
  22. func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFuncImpl) {
  23. ftyp := impl.typ
  24. in := make([]Value, 0, len(ftyp.in))
  25. ap := params
  26. for _, rt := range ftyp.in {
  27. p := unsafe_New(rt)
  28. memmove(p, *(*unsafe.Pointer)(ap), rt.size)
  29. v := Value{rt, p, flag(rt.Kind()) | flagIndir}
  30. in = append(in, v)
  31. ap = (unsafe.Pointer)(uintptr(ap) + ptrSize)
  32. }
  33. out := impl.call(in)
  34. off := uintptr(0)
  35. for i, typ := range ftyp.out {
  36. v := out[i]
  37. if v.typ != typ {
  38. panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
  39. " returned wrong type: have " +
  40. out[i].typ.String() + " for " + typ.String())
  41. }
  42. if v.flag&flagRO != 0 {
  43. panic("reflect: function created by MakeFunc using " + funcName(impl.fn) +
  44. " returned value obtained from unexported field")
  45. }
  46. off = align(off, uintptr(typ.fieldAlign))
  47. addr := unsafe.Pointer(uintptr(results) + off)
  48. if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
  49. *(*unsafe.Pointer)(addr) = v.ptr
  50. } else {
  51. memmove(addr, v.ptr, typ.size)
  52. }
  53. off += typ.size
  54. }
  55. }