PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/cfunction.go

http://github.com/qur/gopy
Go | 171 lines | 131 code | 32 blank | 8 comment | 22 complexity | 3c97f20ea04ae1326f09cff7a09eec84 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright 2011 Julian Phillips. 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 py
  5. // #include "utils.h"
  6. import "C"
  7. import (
  8. "sync"
  9. "unsafe"
  10. )
  11. type CFunction struct {
  12. AbstractObject
  13. o C.PyCFunctionObject
  14. }
  15. func cfunctionCheck(obj Object) bool {
  16. if obj == nil {
  17. return false
  18. }
  19. return C.cFunctionCheck(c(obj)) != 0
  20. }
  21. func newCFunction(obj *C.PyObject) *CFunction {
  22. return (*CFunction)(unsafe.Pointer(obj))
  23. }
  24. func NewCFunction(name string, fn interface{}, doc string) (*CFunction, error) {
  25. return makeCFunction(name, fn, doc, nil)
  26. }
  27. func makeCFunction(name string, fn interface{}, doc string, mod_name *C.PyObject) (*CFunction, error) {
  28. ml := C.newMethodDef()
  29. switch fn.(type) {
  30. case func() (Object, error):
  31. C.set_call_noargs(&ml.ml_meth)
  32. ml.ml_flags = C.METH_NOARGS
  33. case func(a *Tuple) (Object, error):
  34. C.set_call_args(&ml.ml_meth)
  35. ml.ml_flags = C.METH_VARARGS
  36. case func(a *Tuple, k *Dict) (Object, error):
  37. C.set_call_keywords(&ml.ml_meth)
  38. ml.ml_flags = C.METH_VARARGS | C.METH_KEYWORDS
  39. default:
  40. C.free(unsafe.Pointer(ml))
  41. return nil, TypeError.Err("CFunction_New: unknown func type for %s", name)
  42. }
  43. ret := C.PyCFunction_NewEx(ml, saveFunc(fn), mod_name)
  44. if ret == nil {
  45. C.free(unsafe.Pointer(ml))
  46. return nil, exception()
  47. }
  48. ml.ml_name = C.CString(name)
  49. ml.ml_doc = C.CString(doc)
  50. return newCFunction(ret), nil
  51. }
  52. // PyCFunction_GetFunction
  53. func (f *CFunction) Self() (Object, error) {
  54. ret := C.PyCFunction_GetSelf(c(f))
  55. if ret == nil {
  56. return nil, exception()
  57. }
  58. return newObject(ret), nil
  59. }
  60. func (f *CFunction) Flags() (int, error) {
  61. ret := C.PyCFunction_GetFlags(c(f))
  62. return int(ret), exception()
  63. }
  64. func (f *CFunction) Call(args *Tuple, kw *Dict) (Object, error) {
  65. ret := C.PyCFunction_Call(c(f), c(args), c(kw))
  66. if ret == nil {
  67. return nil, exception()
  68. }
  69. return newObject(ret), nil
  70. }
  71. type Method struct {
  72. Name string
  73. Func interface{}
  74. Doc string
  75. }
  76. var (
  77. funcLock sync.RWMutex
  78. funcs []interface{}
  79. )
  80. func saveFunc(f interface{}) *C.PyObject {
  81. funcLock.Lock()
  82. defer funcLock.Unlock()
  83. funcs = append(funcs, f)
  84. return C.PyInt_FromLong(C.long(len(funcs) - 1))
  85. }
  86. func getFunc(self unsafe.Pointer) interface{} {
  87. funcLock.RLock()
  88. defer funcLock.RUnlock()
  89. idx := int(C.PyInt_AsLong((*C.PyObject)(self)))
  90. if idx >= len(funcs) {
  91. return nil
  92. }
  93. return funcs[idx]
  94. }
  95. //export callWithoutArgs
  96. func callWithoutArgs(self, args unsafe.Pointer) unsafe.Pointer {
  97. f, ok := getFunc(self).(func() (Object, error))
  98. if !ok {
  99. raise(AssertionError.Err("callWithoutArgs: wrong function type!!!"))
  100. return nil
  101. }
  102. ret, err := f()
  103. if err != nil {
  104. raise(err)
  105. return nil
  106. }
  107. return unsafe.Pointer(c(ret))
  108. }
  109. //export callWithArgs
  110. func callWithArgs(self, args unsafe.Pointer) unsafe.Pointer {
  111. f, ok := getFunc(self).(func(a *Tuple) (Object, error))
  112. if !ok {
  113. raise(AssertionError.Err("callWithArgs: wrong function type!!!"))
  114. return nil
  115. }
  116. a := newTuple((*C.PyObject)(args))
  117. ret, err := f(a)
  118. if err != nil {
  119. raise(err)
  120. return nil
  121. }
  122. return unsafe.Pointer(c(ret))
  123. }
  124. //export callWithKeywords
  125. func callWithKeywords(self, args, kw unsafe.Pointer) unsafe.Pointer {
  126. f, ok := getFunc(self).(func(a *Tuple, k *Dict) (Object, error))
  127. if !ok {
  128. raise(AssertionError.Err("callWithKeywords: wrong function type!!!"))
  129. return nil
  130. }
  131. a := newTuple((*C.PyObject)(args))
  132. k := newDict((*C.PyObject)(kw))
  133. ret, err := f(a, k)
  134. if err != nil {
  135. raise(err)
  136. return nil
  137. }
  138. return unsafe.Pointer(c(ret))
  139. }