cffi.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. #pragma once
  2. #include "common.h"
  3. #include "vm.h"
  4. namespace pkpy {
  5. #define PY_CLASS(T, mod, name) \
  6. static Type _type(VM* vm) { \
  7. static const StrName __x0(#mod); \
  8. static const StrName __x1(#name); \
  9. return OBJ_GET(Type, vm->_modules[__x0]->attr(__x1)); \
  10. } \
  11. static void _check_type(VM* vm, PyObject* val){ \
  12. if(!vm->isinstance(val, T::_type(vm))){ \
  13. vm->TypeError("expected '" #mod "." #name "', got " + OBJ_NAME(vm->_t(val)).escape()); \
  14. } \
  15. } \
  16. static PyObject* register_class(VM* vm, PyObject* mod) { \
  17. if(OBJ_NAME(mod) != #mod) { \
  18. auto msg = fmt("register_class() failed: ", OBJ_NAME(mod), " != ", #mod); \
  19. throw std::runtime_error(msg); \
  20. } \
  21. PyObject* type = vm->new_type_object(mod, #name, vm->tp_object); \
  22. T::_register(vm, mod, type); \
  23. type->attr()._try_perfect_rehash(); \
  24. return type; \
  25. }
  26. #define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), T(__VA_ARGS__))
  27. static int c99_sizeof(VM*, const Str&);
  28. struct VoidP{
  29. PY_CLASS(VoidP, c, void_p)
  30. void* ptr;
  31. int base_offset;
  32. VoidP(void* ptr): ptr(ptr), base_offset(1){}
  33. VoidP(): ptr(nullptr), base_offset(1){}
  34. static void _register(VM* vm, PyObject* mod, PyObject* type){
  35. vm->bind_default_constructor<VoidP>(type);
  36. vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
  37. VoidP& self = _CAST(VoidP&, args[0]);
  38. std::stringstream ss;
  39. ss << "<void* at " << self.ptr;
  40. if(self.base_offset != 1) ss << ", base_offset=" << self.base_offset;
  41. ss << ">";
  42. return VAR(ss.str());
  43. });
  44. vm->bind_method<1>(type, "__eq__", [](VM* vm, ArgsView args){
  45. VoidP& self = _CAST(VoidP&, args[0]);
  46. VoidP& other = CAST(VoidP&, args[1]);
  47. return VAR(self.ptr == other.ptr && self.base_offset == other.base_offset);
  48. });
  49. vm->bind_method<1>(type, "__ne__", [](VM* vm, ArgsView args){
  50. VoidP& self = _CAST(VoidP&, args[0]);
  51. VoidP& other = CAST(VoidP&, args[1]);
  52. return VAR(self.ptr != other.ptr || self.base_offset != other.base_offset);
  53. });
  54. vm->bind_method<1>(type, "set_base_offset", [](VM* vm, ArgsView args){
  55. VoidP& self = _CAST(VoidP&, args[0]);
  56. if(is_non_tagged_type(args[1], vm->tp_str)){
  57. const Str& type = _CAST(Str&, args[1]);
  58. self.base_offset = c99_sizeof(vm, type);
  59. }else{
  60. self.base_offset = CAST(int, args[1]);
  61. }
  62. return vm->None;
  63. });
  64. vm->bind_method<0>(type, "get_base_offset", [](VM* vm, ArgsView args){
  65. VoidP& self = _CAST(VoidP&, args[0]);
  66. return VAR(self.base_offset);
  67. });
  68. vm->bind_method<1>(type, "offset", [](VM* vm, ArgsView args){
  69. VoidP& self = _CAST(VoidP&, args[0]);
  70. i64 offset = CAST(i64, args[1]);
  71. return VAR_T(VoidP, (char*)self.ptr + offset * self.base_offset);
  72. });
  73. vm->bind_method<1>(type, "__add__", [](VM* vm, ArgsView args){
  74. VoidP& self = _CAST(VoidP&, args[0]);
  75. i64 offset = CAST(i64, args[1]);
  76. return VAR_T(VoidP, (char*)self.ptr + offset);
  77. });
  78. vm->bind_method<1>(type, "__sub__", [](VM* vm, ArgsView args){
  79. VoidP& self = _CAST(VoidP&, args[0]);
  80. i64 offset = CAST(i64, args[1]);
  81. return VAR_T(VoidP, (char*)self.ptr - offset);
  82. });
  83. #define BIND_SETGET(T, name) \
  84. vm->bind_method<0>(type, "read_" name, [](VM* vm, ArgsView args){ \
  85. VoidP& self = _CAST(VoidP&, args[0]); \
  86. return VAR(*(T*)self.ptr); \
  87. }); \
  88. vm->bind_method<1>(type, "write_" name, [](VM* vm, ArgsView args){ \
  89. VoidP& self = _CAST(VoidP&, args[0]); \
  90. *(T*)self.ptr = CAST(T, args[1]); \
  91. return vm->None; \
  92. });
  93. BIND_SETGET(char, "char")
  94. BIND_SETGET(unsigned char, "uchar")
  95. BIND_SETGET(short, "short")
  96. BIND_SETGET(unsigned short, "ushort")
  97. BIND_SETGET(int, "int")
  98. BIND_SETGET(unsigned int, "uint")
  99. BIND_SETGET(long, "long")
  100. BIND_SETGET(unsigned long, "ulong")
  101. BIND_SETGET(long long, "longlong")
  102. BIND_SETGET(unsigned long long, "ulonglong")
  103. BIND_SETGET(float, "float")
  104. BIND_SETGET(double, "double")
  105. BIND_SETGET(bool, "bool")
  106. vm->bind_method<0>(type, "read_void_p", [](VM* vm, ArgsView args){
  107. VoidP& self = _CAST(VoidP&, args[0]);
  108. return VAR_T(VoidP, *(void**)self.ptr);
  109. });
  110. vm->bind_method<1>(type, "write_void_p", [](VM* vm, ArgsView args){
  111. VoidP& self = _CAST(VoidP&, args[0]);
  112. VoidP& other = CAST(VoidP&, args[0]);
  113. self.ptr = other.ptr;
  114. return vm->None;
  115. });
  116. vm->bind_method<1>(type, "read_bytes", [](VM* vm, ArgsView args){
  117. VoidP& self = _CAST(VoidP&, args[0]);
  118. i64 size = CAST(i64, args[1]);
  119. std::vector<char> buffer(size);
  120. memcpy(buffer.data(), self.ptr, size);
  121. return VAR(Bytes(std::move(buffer)));
  122. });
  123. vm->bind_method<1>(type, "write_bytes", [](VM* vm, ArgsView args){
  124. VoidP& self = _CAST(VoidP&, args[0]);
  125. Bytes& bytes = CAST(Bytes&, args[1]);
  126. memcpy(self.ptr, bytes.data(), bytes.size());
  127. return vm->None;
  128. });
  129. }
  130. };
  131. struct C99Struct{
  132. PY_CLASS(C99Struct, c, struct)
  133. static constexpr int INLINE_SIZE = 24;
  134. char _inlined[INLINE_SIZE];
  135. char* p;
  136. int size;
  137. void _init(int size){
  138. this->size = size;
  139. if(size <= INLINE_SIZE){
  140. p = _inlined;
  141. }else{
  142. p = (char*)malloc(size);
  143. }
  144. }
  145. template<typename T>
  146. C99Struct(const T& data){
  147. static_assert(std::is_pod_v<T>);
  148. static_assert(!std::is_pointer_v<T>);
  149. _init(sizeof(T));
  150. memcpy(p, &data, this->size);
  151. }
  152. C99Struct() { p = _inlined; }
  153. C99Struct(void* p, int size){
  154. _init(size);
  155. if(p!=nullptr) memcpy(this->p, p, size);
  156. }
  157. ~C99Struct(){ if(p!=_inlined) free(p); }
  158. C99Struct(const C99Struct& other){
  159. _init(other.size);
  160. memcpy(p, other.p, size);
  161. }
  162. static void _register(VM* vm, PyObject* mod, PyObject* type){
  163. vm->bind_default_constructor<C99Struct>(type);
  164. vm->bind_method<0>(type, "addr", [](VM* vm, ArgsView args){
  165. C99Struct& self = _CAST(C99Struct&, args[0]);
  166. return VAR_T(VoidP, self.p);
  167. });
  168. vm->bind_method<0>(type, "size", [](VM* vm, ArgsView args){
  169. C99Struct& self = _CAST(C99Struct&, args[0]);
  170. return VAR(self.size);
  171. });
  172. vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
  173. const C99Struct& self = _CAST(C99Struct&, args[0]);
  174. return VAR_T(C99Struct, self);
  175. });
  176. // patch VoidP
  177. type = vm->_t(VoidP::_type(vm));
  178. vm->bind_method<1>(type, "read_struct", [](VM* vm, ArgsView args){
  179. VoidP& self = _CAST(VoidP&, args[0]);
  180. const Str& type = CAST(Str&, args[1]);
  181. int size = c99_sizeof(vm, type);
  182. return VAR_T(C99Struct, self.ptr, size);
  183. });
  184. vm->bind_method<1>(type, "write_struct", [](VM* vm, ArgsView args){
  185. VoidP& self = _CAST(VoidP&, args[0]);
  186. C99Struct& other = CAST(C99Struct&, args[1]);
  187. memcpy(self.ptr, other.p, other.size);
  188. return vm->None;
  189. });
  190. }
  191. };
  192. struct ReflType{
  193. std::string_view name;
  194. size_t size;
  195. std::map<std::string_view, int> fields;
  196. };
  197. inline static std::map<std::string_view, ReflType> _refl_types;
  198. inline void add_refl_type(std::string_view name, size_t size, std::initializer_list<std::pair<std::string_view, int>> fields){
  199. ReflType type{name, size, {}};
  200. for(auto& [name, offset] : fields){
  201. type.fields[name] = offset;
  202. }
  203. _refl_types[name] = std::move(type);
  204. }
  205. inline static int c99_sizeof(VM* vm, const Str& type){
  206. static const std::map<std::string_view, i64> c99_sizes = {
  207. {"char", sizeof(char)},
  208. {"uchar", sizeof(unsigned char)},
  209. {"short", sizeof(short)},
  210. {"ushort", sizeof(unsigned short)},
  211. {"int", sizeof(int)},
  212. {"uint", sizeof(unsigned int)},
  213. {"long", sizeof(long)},
  214. {"ulong", sizeof(unsigned long)},
  215. {"longlong", sizeof(long long)},
  216. {"ulonglong", sizeof(unsigned long long)},
  217. {"float", sizeof(float)},
  218. {"double", sizeof(double)},
  219. {"bool", sizeof(bool)},
  220. {"void_p", sizeof(void*)}
  221. };
  222. auto it = c99_sizes.find(type.sv());
  223. if(it != c99_sizes.end()) return it->second;
  224. auto it2 = _refl_types.find(type.sv());
  225. if(it2 != _refl_types.end()) return it2->second.size;
  226. vm->ValueError("not a valid c99 type");
  227. return 0;
  228. }
  229. struct C99ReflType final: ReflType{
  230. PY_CLASS(C99ReflType, c, _refl)
  231. C99ReflType(const ReflType& type){
  232. this->name = type.name;
  233. this->size = type.size;
  234. this->fields = type.fields;
  235. }
  236. static void _register(VM* vm, PyObject* mod, PyObject* type){
  237. vm->bind_constructor<-1>(type, CPP_NOT_IMPLEMENTED());
  238. vm->bind_method<0>(type, "__call__", [](VM* vm, ArgsView args){
  239. C99ReflType& self = _CAST(C99ReflType&, args[0]);
  240. return VAR_T(C99Struct, nullptr, self.size);
  241. });
  242. vm->bind_method<0>(type, "name", [](VM* vm, ArgsView args){
  243. C99ReflType& self = _CAST(C99ReflType&, args[0]);
  244. return VAR(self.name);
  245. });
  246. vm->bind_method<0>(type, "size", [](VM* vm, ArgsView args){
  247. C99ReflType& self = _CAST(C99ReflType&, args[0]);
  248. return VAR(self.size);
  249. });
  250. vm->bind_method<1>(type, "__getitem__", [](VM* vm, ArgsView args){
  251. C99ReflType& self = _CAST(C99ReflType&, args[0]);
  252. const Str& name = CAST(Str&, args[1]);
  253. auto it = self.fields.find(name.sv());
  254. if(it == self.fields.end()){
  255. vm->_error("KeyError", name.escape());
  256. return vm->None;
  257. }
  258. return VAR(it->second);
  259. });
  260. }
  261. };
  262. static_assert(sizeof(Py_<C99Struct>) <= 64);
  263. inline PyObject* py_var(VM* vm, void* p){
  264. return VAR_T(VoidP, p);
  265. }
  266. inline PyObject* py_var(VM* vm, char* p){
  267. return VAR_T(VoidP, p);
  268. }
  269. /***********************************************/
  270. template<typename T>
  271. T to_void_p(VM* vm, PyObject* var){
  272. static_assert(std::is_pointer_v<T>);
  273. VoidP& p = CAST(VoidP&, var);
  274. return reinterpret_cast<T>(p.ptr);
  275. }
  276. template<typename T>
  277. T to_c99_struct(VM* vm, PyObject* var){
  278. static_assert(std::is_pod_v<T>);
  279. C99Struct& pod = CAST(C99Struct&, var);
  280. return *reinterpret_cast<T*>(pod.p);
  281. }
  282. template<typename T>
  283. std::enable_if_t<std::is_pod_v<T> && !std::is_pointer_v<T>, PyObject*> py_var(VM* vm, const T& data){
  284. return VAR_T(C99Struct, data);
  285. }
  286. /*****************************************************************/
  287. struct NativeProxyFuncCBase {
  288. virtual PyObject* operator()(VM* vm, ArgsView args) = 0;
  289. static void check_args_size(VM* vm, ArgsView args, int n){
  290. if (args.size() != n){
  291. vm->TypeError("expected " + std::to_string(n) + " arguments, but got " + std::to_string(args.size()));
  292. }
  293. }
  294. };
  295. template<typename Ret, typename... Params>
  296. struct NativeProxyFuncC final: NativeProxyFuncCBase {
  297. static constexpr int N = sizeof...(Params);
  298. using _Fp = Ret(*)(Params...);
  299. _Fp func;
  300. NativeProxyFuncC(_Fp func) : func(func) {}
  301. PyObject* operator()(VM* vm, ArgsView args) override {
  302. check_args_size(vm, args, N);
  303. return call<Ret>(vm, args, std::make_index_sequence<N>());
  304. }
  305. template<typename __Ret, size_t... Is>
  306. PyObject* call(VM* vm, ArgsView args, std::index_sequence<Is...>){
  307. if constexpr(std::is_void_v<__Ret>){
  308. func(py_cast<Params>(vm, args[Is])...);
  309. return vm->None;
  310. }else{
  311. __Ret ret = func(py_cast<Params>(vm, args[Is])...);
  312. return VAR(std::move(ret));
  313. }
  314. }
  315. };
  316. inline PyObject* _any_c_wrapper(VM* vm, ArgsView args){
  317. static const StrName m_proxy("__proxy__");
  318. NativeProxyFuncCBase* pf = CAST(NativeProxyFuncCBase*, args[-2]->attr(m_proxy));
  319. return (*pf)(vm, args);
  320. }
  321. template<typename T>
  322. inline void bind_any_c_fp(VM* vm, PyObject* obj, Str name, T fp){
  323. static_assert(std::is_pod_v<T>);
  324. static_assert(std::is_pointer_v<T>);
  325. auto proxy = new NativeProxyFuncC(fp);
  326. PyObject* func = VAR(NativeFunc(_any_c_wrapper, proxy->N, false));
  327. func->attr().set("__proxy__", VAR_T(VoidP, proxy));
  328. obj->attr().set(name, func);
  329. }
  330. inline void add_module_c(VM* vm){
  331. PyObject* mod = vm->new_module("c");
  332. vm->bind_func<1>(mod, "malloc", [](VM* vm, ArgsView args){
  333. i64 size = CAST(i64, args[0]);
  334. return VAR(malloc(size));
  335. });
  336. vm->bind_func<1>(mod, "free", [](VM* vm, ArgsView args){
  337. void* p = CAST(void*, args[0]);
  338. free(p);
  339. return vm->None;
  340. });
  341. vm->bind_func<1>(mod, "sizeof", [](VM* vm, ArgsView args){
  342. const Str& type = CAST(Str&, args[0]);
  343. i64 size = c99_sizeof(vm, type);
  344. return VAR(size);
  345. });
  346. vm->bind_func<1>(mod, "refl", [](VM* vm, ArgsView args){
  347. const Str& key = CAST(Str&, args[0]);
  348. auto it = _refl_types.find(key.sv());
  349. if(it == _refl_types.end()) vm->ValueError("reflection type not found");
  350. const ReflType& rt = it->second;
  351. return VAR_T(C99ReflType, rt);
  352. });
  353. vm->bind_func<3>(mod, "memset", [](VM* vm, ArgsView args){
  354. void* p = CAST(void*, args[0]);
  355. i64 c = CAST(i64, args[1]);
  356. i64 size = CAST(i64, args[2]);
  357. memset(p, c, size);
  358. return vm->None;
  359. });
  360. vm->bind_func<3>(mod, "memcpy", [](VM* vm, ArgsView args){
  361. void* dst = CAST(void*, args[0]);
  362. void* src = CAST(void*, args[1]);
  363. i64 size = CAST(i64, args[2]);
  364. memcpy(dst, src, size);
  365. return vm->None;
  366. });
  367. VoidP::register_class(vm, mod);
  368. C99Struct::register_class(vm, mod);
  369. C99ReflType::register_class(vm, mod);
  370. mod->attr().set("NULL", VAR_T(VoidP, nullptr));
  371. }
  372. } // namespace pkpy