cffi.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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, "__add__", [](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, "__sub__", [](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 * self.base_offset);
  77. });
  78. #define BIND_SETGET(T, name) \
  79. vm->bind_method<0>(type, "read_" name, [](VM* vm, ArgsView args){ \
  80. VoidP& self = _CAST(VoidP&, args[0]); \
  81. return VAR(*(T*)self.ptr); \
  82. }); \
  83. vm->bind_method<1>(type, "write_" name, [](VM* vm, ArgsView args){ \
  84. VoidP& self = _CAST(VoidP&, args[0]); \
  85. *(T*)self.ptr = CAST(T, args[1]); \
  86. return vm->None; \
  87. });
  88. BIND_SETGET(char, "char")
  89. BIND_SETGET(unsigned char, "uchar")
  90. BIND_SETGET(short, "short")
  91. BIND_SETGET(unsigned short, "ushort")
  92. BIND_SETGET(int, "int")
  93. BIND_SETGET(unsigned int, "uint")
  94. BIND_SETGET(long, "long")
  95. BIND_SETGET(unsigned long, "ulong")
  96. BIND_SETGET(long long, "longlong")
  97. BIND_SETGET(unsigned long long, "ulonglong")
  98. BIND_SETGET(float, "float")
  99. BIND_SETGET(double, "double")
  100. BIND_SETGET(bool, "bool")
  101. vm->bind_method<0>(type, "read_void_p", [](VM* vm, ArgsView args){
  102. VoidP& self = _CAST(VoidP&, args[0]);
  103. return VAR_T(VoidP, *(void**)self.ptr);
  104. });
  105. vm->bind_method<1>(type, "write_void_p", [](VM* vm, ArgsView args){
  106. VoidP& self = _CAST(VoidP&, args[0]);
  107. VoidP& other = CAST(VoidP&, args[0]);
  108. self.ptr = other.ptr;
  109. return vm->None;
  110. });
  111. vm->bind_method<1>(type, "read_bytes", [](VM* vm, ArgsView args){
  112. VoidP& self = _CAST(VoidP&, args[0]);
  113. i64 size = CAST(i64, args[1]);
  114. std::vector<char> buffer(size);
  115. memcpy(buffer.data(), self.ptr, size);
  116. return VAR(Bytes(std::move(buffer)));
  117. });
  118. vm->bind_method<1>(type, "write_bytes", [](VM* vm, ArgsView args){
  119. VoidP& self = _CAST(VoidP&, args[0]);
  120. Bytes& bytes = CAST(Bytes&, args[1]);
  121. memcpy(self.ptr, bytes.data(), bytes.size());
  122. return vm->None;
  123. });
  124. }
  125. };
  126. struct C99Struct{
  127. PY_CLASS(C99Struct, c, struct)
  128. static constexpr int INLINE_SIZE = 24;
  129. char _inlined[INLINE_SIZE];
  130. char* p;
  131. int size;
  132. void _init(int size){
  133. this->size = size;
  134. if(size <= INLINE_SIZE){
  135. p = _inlined;
  136. }else{
  137. p = (char*)malloc(size);
  138. }
  139. }
  140. template<typename T>
  141. C99Struct(const T& data){
  142. static_assert(std::is_pod_v<T>);
  143. static_assert(!std::is_pointer_v<T>);
  144. _init(sizeof(T));
  145. memcpy(p, &data, this->size);
  146. }
  147. C99Struct() { p = _inlined; }
  148. C99Struct(void* p, int size){
  149. _init(size);
  150. memcpy(this->p, p, size);
  151. }
  152. ~C99Struct(){ if(p!=_inlined) free(p); }
  153. C99Struct(const C99Struct& other){
  154. _init(other.size);
  155. memcpy(p, other.p, size);
  156. }
  157. static void _register(VM* vm, PyObject* mod, PyObject* type){
  158. vm->bind_default_constructor<C99Struct>(type);
  159. vm->bind_method<0>(type, "address", [](VM* vm, ArgsView args){
  160. C99Struct& self = _CAST(C99Struct&, args[0]);
  161. return VAR_T(VoidP, self.p);
  162. });
  163. vm->bind_method<0>(type, "size", [](VM* vm, ArgsView args){
  164. C99Struct& self = _CAST(C99Struct&, args[0]);
  165. return VAR(self.size);
  166. });
  167. vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
  168. const C99Struct& self = _CAST(C99Struct&, args[0]);
  169. return VAR_T(C99Struct, self);
  170. });
  171. // patch VoidP
  172. type = vm->_t(VoidP::_type(vm));
  173. vm->bind_method<1>(type, "read_struct", [](VM* vm, ArgsView args){
  174. VoidP& self = _CAST(VoidP&, args[0]);
  175. const Str& type = CAST(Str&, args[1]);
  176. int size = c99_sizeof(vm, type);
  177. return VAR_T(C99Struct, self.ptr, size);
  178. });
  179. vm->bind_method<1>(type, "write_struct", [](VM* vm, ArgsView args){
  180. VoidP& self = _CAST(VoidP&, args[0]);
  181. C99Struct& other = CAST(C99Struct&, args[1]);
  182. memcpy(self.ptr, other.p, other.size);
  183. return vm->None;
  184. });
  185. }
  186. };
  187. struct ReflField{
  188. std::string_view name;
  189. int offset;
  190. };
  191. struct ReflType{
  192. std::string_view name;
  193. size_t size;
  194. std::vector<ReflField> fields;
  195. };
  196. inline static std::map<std::string_view, ReflType> _refl_types;
  197. inline void add_refl_type(std::string_view name, size_t size, std::initializer_list<ReflField> fields){
  198. _refl_types[name] = {name, size, fields};
  199. }
  200. inline static int c99_sizeof(VM* vm, const Str& type){
  201. static const std::map<std::string_view, i64> c99_sizes = {
  202. {"char", sizeof(char)},
  203. {"uchar", sizeof(unsigned char)},
  204. {"short", sizeof(short)},
  205. {"ushort", sizeof(unsigned short)},
  206. {"int", sizeof(int)},
  207. {"uint", sizeof(unsigned int)},
  208. {"long", sizeof(long)},
  209. {"ulong", sizeof(unsigned long)},
  210. {"longlong", sizeof(long long)},
  211. {"ulonglong", sizeof(unsigned long long)},
  212. {"float", sizeof(float)},
  213. {"double", sizeof(double)},
  214. {"bool", sizeof(bool)},
  215. {"void_p", sizeof(void*)}
  216. };
  217. auto it = c99_sizes.find(type.sv());
  218. if(it != c99_sizes.end()) return it->second;
  219. auto it2 = _refl_types.find(type.sv());
  220. if(it2 != _refl_types.end()) return it2->second.size;
  221. vm->ValueError("not a valid c99 type");
  222. return 0;
  223. }
  224. struct C99ReflType{
  225. PY_CLASS(C99ReflType, c, "_refl")
  226. static void _register(VM* vm, PyObject* mod, PyObject* type){
  227. vm->bind_constructor<-1>(type, CPP_NOT_IMPLEMENTED());
  228. }
  229. };
  230. static_assert(sizeof(Py_<C99Struct>) <= 64);
  231. inline PyObject* py_var(VM* vm, void* p){
  232. return VAR_T(VoidP, p);
  233. }
  234. inline PyObject* py_var(VM* vm, char* p){
  235. return VAR_T(VoidP, p);
  236. }
  237. /***********************************************/
  238. template<typename T>
  239. T to_void_p(VM* vm, PyObject* var){
  240. static_assert(std::is_pointer_v<T>);
  241. VoidP& p = CAST(VoidP&, var);
  242. return reinterpret_cast<T>(p.ptr);
  243. }
  244. template<typename T>
  245. T to_c99_struct(VM* vm, PyObject* var){
  246. static_assert(std::is_pod_v<T>);
  247. C99Struct& pod = CAST(C99Struct&, var);
  248. return *reinterpret_cast<T*>(pod.p);
  249. }
  250. template<typename T>
  251. std::enable_if_t<std::is_pod_v<T> && !std::is_pointer_v<T>, PyObject*> py_var(VM* vm, const T& data){
  252. return VAR_T(C99Struct, data);
  253. }
  254. /*****************************************************************/
  255. struct NativeProxyFuncCBase {
  256. virtual PyObject* operator()(VM* vm, ArgsView args) = 0;
  257. static void check_args_size(VM* vm, ArgsView args, int n){
  258. if (args.size() != n){
  259. vm->TypeError("expected " + std::to_string(n) + " arguments, but got " + std::to_string(args.size()));
  260. }
  261. }
  262. };
  263. template<typename Ret, typename... Params>
  264. struct NativeProxyFuncC final: NativeProxyFuncCBase {
  265. static constexpr int N = sizeof...(Params);
  266. using _Fp = Ret(*)(Params...);
  267. _Fp func;
  268. NativeProxyFuncC(_Fp func) : func(func) {}
  269. PyObject* operator()(VM* vm, ArgsView args) override {
  270. check_args_size(vm, args, N);
  271. return call<Ret>(vm, args, std::make_index_sequence<N>());
  272. }
  273. template<typename __Ret, size_t... Is>
  274. PyObject* call(VM* vm, ArgsView args, std::index_sequence<Is...>){
  275. if constexpr(std::is_void_v<__Ret>){
  276. func(py_cast<Params>(vm, args[Is])...);
  277. return vm->None;
  278. }else{
  279. __Ret ret = func(py_cast<Params>(vm, args[Is])...);
  280. return VAR(std::move(ret));
  281. }
  282. }
  283. };
  284. inline PyObject* _any_c_wrapper(VM* vm, ArgsView args){
  285. static const StrName m_proxy("__proxy__");
  286. NativeProxyFuncCBase* pf = CAST(NativeProxyFuncCBase*, args[-2]->attr(m_proxy));
  287. return (*pf)(vm, args);
  288. }
  289. template<typename T>
  290. inline void bind_any_c_fp(VM* vm, PyObject* obj, Str name, T fp){
  291. static_assert(std::is_pod_v<T>);
  292. static_assert(std::is_pointer_v<T>);
  293. auto proxy = new NativeProxyFuncC(fp);
  294. PyObject* func = VAR(NativeFunc(_any_c_wrapper, proxy->N, false));
  295. func->attr().set("__proxy__", VAR_T(VoidP, proxy));
  296. obj->attr().set(name, func);
  297. }
  298. inline void add_module_c(VM* vm){
  299. PyObject* mod = vm->new_module("c");
  300. vm->bind_func<1>(mod, "malloc", [](VM* vm, ArgsView args){
  301. i64 size = CAST(i64, args[0]);
  302. return VAR(malloc(size));
  303. });
  304. vm->bind_func<1>(mod, "free", [](VM* vm, ArgsView args){
  305. void* p = CAST(void*, args[0]);
  306. free(p);
  307. return vm->None;
  308. });
  309. vm->bind_func<1>(mod, "sizeof", [](VM* vm, ArgsView args){
  310. const Str& type = CAST(Str&, args[0]);
  311. i64 size = c99_sizeof(vm, type);
  312. return VAR(size);
  313. });
  314. vm->bind_func<1>(mod, "refl", [](VM* vm, ArgsView args){
  315. const Str& key = CAST(Str&, args[0]);
  316. auto it = _refl_types.find(key.sv());
  317. if(it == _refl_types.end()) vm->ValueError("reflection type not found");
  318. const ReflType& rt = it->second;
  319. PyObject* obj = VAR_T(C99ReflType);
  320. obj->enable_instance_dict();
  321. obj->attr().set("__name__", VAR(rt.name));
  322. obj->attr().set("__size__", VAR(rt.size));
  323. for(auto [k,v]: rt.fields) obj->attr().set(StrName::get(k), VAR(v));
  324. return obj;
  325. });
  326. vm->bind_func<3>(mod, "memset", [](VM* vm, ArgsView args){
  327. void* p = CAST(void*, args[0]);
  328. i64 c = CAST(i64, args[1]);
  329. i64 size = CAST(i64, args[2]);
  330. memset(p, c, size);
  331. return vm->None;
  332. });
  333. vm->bind_func<3>(mod, "memcpy", [](VM* vm, ArgsView args){
  334. void* dst = CAST(void*, args[0]);
  335. void* src = CAST(void*, args[1]);
  336. i64 size = CAST(i64, args[2]);
  337. memcpy(dst, src, size);
  338. return vm->None;
  339. });
  340. VoidP::register_class(vm, mod);
  341. C99Struct::register_class(vm, mod);
  342. C99ReflType::register_class(vm, mod);
  343. mod->attr().set("NULL", VAR_T(VoidP, nullptr));
  344. }
  345. } // namespace pkpy