1
0

bindings.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #pragma once
  2. #include "cffi.h"
  3. namespace pkpy{
  4. struct NativeProxyFuncCBase {
  5. virtual PyObject* operator()(VM* vm, ArgsView args) = 0;
  6. };
  7. template<typename Ret, typename... Params>
  8. struct NativeProxyFuncC final: NativeProxyFuncCBase {
  9. static constexpr int N = sizeof...(Params);
  10. using _Fp = Ret(*)(Params...);
  11. _Fp func;
  12. NativeProxyFuncC(_Fp func) : func(func) {}
  13. PyObject* operator()(VM* vm, ArgsView args) override {
  14. PK_ASSERT(args.size() == N);
  15. return call<Ret>(vm, args, std::make_index_sequence<N>());
  16. }
  17. template<typename __Ret, size_t... Is>
  18. PyObject* call(VM* vm, ArgsView args, std::index_sequence<Is...>){
  19. if constexpr(std::is_void_v<__Ret>){
  20. func(py_cast<Params>(vm, args[Is])...);
  21. return vm->None;
  22. }else{
  23. __Ret ret = func(py_cast<Params>(vm, args[Is])...);
  24. return VAR(std::move(ret));
  25. }
  26. }
  27. };
  28. template<typename Ret, typename T, typename... Params>
  29. struct NativeProxyMethodC final: NativeProxyFuncCBase {
  30. static constexpr int N = sizeof...(Params);
  31. using _Fp = Ret(T::*)(Params...);
  32. _Fp func;
  33. NativeProxyMethodC(_Fp func) : func(func) {}
  34. PyObject* operator()(VM* vm, ArgsView args) override {
  35. PK_ASSERT(args.size() == N+1);
  36. return call<Ret>(vm, args, std::make_index_sequence<N>());
  37. }
  38. template<typename __Ret, size_t... Is>
  39. PyObject* call(VM* vm, ArgsView args, std::index_sequence<Is...>){
  40. T& self = py_cast<T&>(vm, args[0]);
  41. if constexpr(std::is_void_v<__Ret>){
  42. (self.*func)(py_cast<Params>(vm, args[Is+1])...);
  43. return vm->None;
  44. }else{
  45. __Ret ret = (self.*func)(py_cast<Params>(vm, args[Is+1])...);
  46. return VAR(std::move(ret));
  47. }
  48. }
  49. };
  50. inline PyObject* proxy_wrapper(VM* vm, ArgsView args){
  51. NativeProxyFuncCBase* pf = lambda_get_userdata<NativeProxyFuncCBase*>(args.begin());
  52. return (*pf)(vm, args);
  53. }
  54. template<typename Ret, typename... Params>
  55. void _bind(VM* vm, PyObject* obj, const char* sig, Ret(*func)(Params...)){
  56. auto proxy = new NativeProxyFuncC<Ret, Params...>(func);
  57. vm->bind(obj, sig, proxy_wrapper, proxy);
  58. }
  59. template<typename Ret, typename T, typename... Params>
  60. void _bind(VM* vm, PyObject* obj, const char* sig, Ret(T::*func)(Params...)){
  61. auto proxy = new NativeProxyMethodC<Ret, T, Params...>(func);
  62. vm->bind(obj, sig, proxy_wrapper, proxy);
  63. }
  64. /*****************************************************************/
  65. #define PY_FIELD(T, NAME, REF, EXPR) \
  66. vm->bind_property(type, NAME, \
  67. [](VM* vm, ArgsView args){ \
  68. T& self = PK_OBJ_GET(T, args[0]); \
  69. return VAR(self.REF()->EXPR); \
  70. }, \
  71. [](VM* vm, ArgsView args){ \
  72. T& self = PK_OBJ_GET(T, args[0]); \
  73. self.REF()->EXPR = CAST(decltype(self.REF()->EXPR), args[1]); \
  74. return vm->None; \
  75. });
  76. #define PY_FIELD_P(T, NAME, EXPR) \
  77. vm->bind_property(type, NAME, \
  78. [](VM* vm, ArgsView args){ \
  79. VoidP& self = PK_OBJ_GET(VoidP, args[0]); \
  80. T* tgt = reinterpret_cast<T*>(self.ptr); \
  81. return VAR(tgt->EXPR); \
  82. }, \
  83. [](VM* vm, ArgsView args){ \
  84. VoidP& self = PK_OBJ_GET(VoidP, args[0]); \
  85. T* tgt = reinterpret_cast<T*>(self.ptr); \
  86. tgt->EXPR = CAST(decltype(tgt->EXPR), args[1]); \
  87. return vm->None; \
  88. });
  89. #define PY_READONLY_FIELD(T, NAME, REF, EXPR) \
  90. vm->bind_property(type, NAME, \
  91. [](VM* vm, ArgsView args){ \
  92. T& self = PK_OBJ_GET(T, args[0]); \
  93. return VAR(self.REF()->EXPR); \
  94. });
  95. #define PY_READONLY_FIELD_P(T, NAME, EXPR) \
  96. vm->bind_property(type, NAME, \
  97. [](VM* vm, ArgsView args){ \
  98. VoidP& self = PK_OBJ_GET(VoidP, args[0]); \
  99. T* tgt = reinterpret_cast<T*>(self.ptr); \
  100. return VAR(tgt->EXPR); \
  101. });
  102. #define PY_PROPERTY(T, NAME, REF, FGET, FSET) \
  103. vm->bind_property(type, NAME, \
  104. [](VM* vm, ArgsView args){ \
  105. T& self = PK_OBJ_GET(T, args[0]); \
  106. return VAR(self.REF()->FGET()); \
  107. }, \
  108. [](VM* vm, ArgsView args){ \
  109. T& self = _CAST(T&, args[0]); \
  110. using __NT = decltype(self.REF()->FGET()); \
  111. self.REF()->FSET(CAST(__NT, args[1])); \
  112. return vm->None; \
  113. });
  114. #define PY_READONLY_PROPERTY(T, NAME, REF, FGET) \
  115. vm->bind_property(type, NAME, \
  116. [](VM* vm, ArgsView args){ \
  117. T& self = PK_OBJ_GET(T, args[0]); \
  118. return VAR(self.REF()->FGET()); \
  119. });
  120. #define PY_STRUCT_LIKE(wT) \
  121. using vT = std::remove_pointer_t<decltype(std::declval<wT>()._())>; \
  122. static_assert(std::is_trivially_copyable<vT>::value); \
  123. type->attr().set("__struct__", vm->True); \
  124. vm->bind_func<1>(type, "from_struct", [](VM* vm, ArgsView args){ \
  125. C99Struct& s = CAST(C99Struct&, args[0]); \
  126. if(s.size != sizeof(vT)) vm->ValueError("size mismatch"); \
  127. PyObject* obj = vm->heap.gcnew<wT>(wT::_type(vm)); \
  128. memcpy(_CAST(wT&, obj)._(), s.p, sizeof(vT)); \
  129. return obj; \
  130. }, {}, BindType::STATICMETHOD); \
  131. vm->bind_method<0>(type, "to_struct", [](VM* vm, ArgsView args){ \
  132. wT& self = _CAST(wT&, args[0]); \
  133. return VAR_T(C99Struct, self._(), sizeof(vT)); \
  134. }); \
  135. vm->bind_method<0>(type, "addr", [](VM* vm, ArgsView args){ \
  136. wT& self = _CAST(wT&, args[0]); \
  137. return VAR_T(VoidP, self._()); \
  138. }); \
  139. vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){ \
  140. wT& self = _CAST(wT&, args[0]); \
  141. return VAR_T(wT, *self._()); \
  142. }); \
  143. vm->bind_method<0>(type, "sizeof", [](VM* vm, ArgsView args){ \
  144. return VAR(sizeof(vT)); \
  145. }); \
  146. vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
  147. wT& self = _CAST(wT&, _0); \
  148. if(!vm->isinstance(_1, wT::_type(vm))) return vm->NotImplemented; \
  149. wT& other = _CAST(wT&, _1); \
  150. return VAR(self == other); \
  151. }); \
  152. #define PY_POINTER_SETGETITEM(T) \
  153. vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1){ \
  154. VoidP& self = PK_OBJ_GET(VoidP&, _0); \
  155. i64 i = CAST(i64, _1); \
  156. T* tgt = reinterpret_cast<T*>(self.ptr); \
  157. return VAR(tgt[i]); \
  158. }); \
  159. vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0, PyObject* _1, PyObject* _2){ \
  160. VoidP& self = PK_OBJ_GET(VoidP&, _0); \
  161. i64 i = CAST(i64, _1); \
  162. T* tgt = reinterpret_cast<T*>(self.ptr); \
  163. tgt[i] = CAST(T, _2); \
  164. }); \
  165. } // namespace pkpy