cffi.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include "pocketpy/cffi.h"
  2. namespace pkpy{
  3. void VoidP::_register(VM* vm, PyObject* mod, PyObject* type){
  4. vm->bind_default_constructor<VoidP>(type);
  5. vm->bind_func<1>(type, "from_hex", [](VM* vm, ArgsView args){
  6. std::string s = CAST(Str&, args[0]).str();
  7. size_t size;
  8. intptr_t ptr = std::stoll(s, &size, 16);
  9. if(size != s.size()) vm->ValueError("invalid literal for void_p(): " + s);
  10. return VAR_T(VoidP, (void*)ptr);
  11. });
  12. vm->bind_method<0>(type, "hex", [](VM* vm, ArgsView args){
  13. VoidP& self = _CAST(VoidP&, args[0]);
  14. return VAR(self.hex());
  15. });
  16. vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
  17. VoidP& self = _CAST(VoidP&, obj);
  18. std::stringstream ss;
  19. ss << "<void* at " << self.hex() << ">";
  20. return VAR(ss.str());
  21. });
  22. #define BIND_CMP(name, op) \
  23. vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){ \
  24. if(!is_non_tagged_type(rhs, VoidP::_type(vm))) return vm->NotImplemented; \
  25. return VAR(_CAST(VoidP&, lhs) op _CAST(VoidP&, rhs)); \
  26. });
  27. BIND_CMP(__eq__, ==)
  28. BIND_CMP(__lt__, <)
  29. BIND_CMP(__le__, <=)
  30. BIND_CMP(__gt__, >)
  31. BIND_CMP(__ge__, >=)
  32. #undef BIND_CMP
  33. vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
  34. VoidP& self = _CAST(VoidP&, obj);
  35. return reinterpret_cast<i64>(self.ptr);
  36. });
  37. vm->bind__add__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
  38. VoidP& self = _CAST(VoidP&, lhs);
  39. i64 offset = CAST(i64, rhs);
  40. return VAR_T(VoidP, (char*)self.ptr + offset);
  41. });
  42. vm->bind__sub__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
  43. VoidP& self = _CAST(VoidP&, lhs);
  44. i64 offset = CAST(i64, rhs);
  45. return VAR_T(VoidP, (char*)self.ptr - offset);
  46. });
  47. #define BIND_SETGET(T, name) \
  48. vm->bind_method<0>(type, "read_" name, [](VM* vm, ArgsView args){ \
  49. VoidP& self = _CAST(VoidP&, args[0]); \
  50. return VAR(*(T*)self.ptr); \
  51. }); \
  52. vm->bind_method<1>(type, "write_" name, [](VM* vm, ArgsView args){ \
  53. VoidP& self = _CAST(VoidP&, args[0]); \
  54. *(T*)self.ptr = CAST(T, args[1]); \
  55. return vm->None; \
  56. });
  57. BIND_SETGET(char, "char")
  58. BIND_SETGET(unsigned char, "uchar")
  59. BIND_SETGET(short, "short")
  60. BIND_SETGET(unsigned short, "ushort")
  61. BIND_SETGET(int, "int")
  62. BIND_SETGET(unsigned int, "uint")
  63. BIND_SETGET(long, "long")
  64. BIND_SETGET(unsigned long, "ulong")
  65. BIND_SETGET(long long, "longlong")
  66. BIND_SETGET(unsigned long long, "ulonglong")
  67. BIND_SETGET(float, "float")
  68. BIND_SETGET(double, "double")
  69. BIND_SETGET(bool, "bool")
  70. BIND_SETGET(void*, "void_p")
  71. vm->bind_method<1>(type, "read_bytes", [](VM* vm, ArgsView args){
  72. VoidP& self = _CAST(VoidP&, args[0]);
  73. i64 size = CAST(i64, args[1]);
  74. std::vector<char> buffer(size);
  75. memcpy(buffer.data(), self.ptr, size);
  76. return VAR(Bytes(std::move(buffer)));
  77. });
  78. vm->bind_method<1>(type, "write_bytes", [](VM* vm, ArgsView args){
  79. VoidP& self = _CAST(VoidP&, args[0]);
  80. Bytes& bytes = CAST(Bytes&, args[1]);
  81. memcpy(self.ptr, bytes.data(), bytes.size());
  82. return vm->None;
  83. });
  84. #undef BIND_SETGET
  85. }
  86. void C99Struct::_register(VM* vm, PyObject* mod, PyObject* type){
  87. vm->bind_constructor<2>(type, [](VM* vm, ArgsView args){
  88. Type cls = PK_OBJ_GET(Type, args[0]);
  89. if(is_int(args[1])){
  90. int size = _CAST(int, args[1]);
  91. return vm->heap.gcnew<C99Struct>(cls, size);
  92. }
  93. if(is_non_tagged_type(args[1], vm->tp_bytes)){
  94. const Bytes& b = _CAST(Bytes&, args[1]);
  95. return vm->heap.gcnew<C99Struct>(cls, (void*)b.data(), b.size());
  96. }
  97. vm->TypeError("expected int or bytes");
  98. return vm->None;
  99. });
  100. vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
  101. C99Struct& self = _CAST(C99Struct&, obj);
  102. std::stringstream ss;
  103. ss << "<struct object of " << self.size << " bytes>";
  104. return VAR(ss.str());
  105. });
  106. vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
  107. C99Struct& self = _CAST(C99Struct&, obj);
  108. std::string_view view((char*)self.p, self.size);
  109. return (i64)std::hash<std::string_view>()(view);
  110. });
  111. vm->bind_method<0>(type, "addr", [](VM* vm, ArgsView args){
  112. C99Struct& self = _CAST(C99Struct&, args[0]);
  113. return VAR_T(VoidP, self.p);
  114. });
  115. vm->bind_method<0>(type, "size", [](VM* vm, ArgsView args){
  116. C99Struct& self = _CAST(C99Struct&, args[0]);
  117. return VAR(self.size);
  118. });
  119. vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
  120. const C99Struct& self = _CAST(C99Struct&, args[0]);
  121. return VAR_T(C99Struct, self);
  122. });
  123. vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* lhs, PyObject* rhs){
  124. C99Struct& self = _CAST(C99Struct&, lhs);
  125. if(!is_non_tagged_type(rhs, C99Struct::_type(vm))) return vm->NotImplemented;
  126. C99Struct& other = _CAST(C99Struct&, rhs);
  127. bool ok = self.size == other.size && memcmp(self.p, other.p, self.size) == 0;
  128. return VAR(ok);
  129. });
  130. #define BIND_SETGET(T, name) \
  131. vm->bind(type, "read_" name "(self, offset=0)", [](VM* vm, ArgsView args){ \
  132. C99Struct& self = _CAST(C99Struct&, args[0]); \
  133. i64 offset = CAST(i64, args[1]); \
  134. void* ptr = self.p + offset; \
  135. return VAR(*(T*)ptr); \
  136. }); \
  137. vm->bind(type, "write_" name "(self, value, offset=0)", [](VM* vm, ArgsView args){ \
  138. C99Struct& self = _CAST(C99Struct&, args[0]); \
  139. i64 offset = CAST(i64, args[2]); \
  140. void* ptr = self.p + offset; \
  141. *(T*)ptr = CAST(T, args[1]); \
  142. return vm->None; \
  143. });
  144. BIND_SETGET(char, "char")
  145. BIND_SETGET(unsigned char, "uchar")
  146. BIND_SETGET(short, "short")
  147. BIND_SETGET(unsigned short, "ushort")
  148. BIND_SETGET(int, "int")
  149. BIND_SETGET(unsigned int, "uint")
  150. BIND_SETGET(long, "long")
  151. BIND_SETGET(unsigned long, "ulong")
  152. BIND_SETGET(long long, "longlong")
  153. BIND_SETGET(unsigned long long, "ulonglong")
  154. BIND_SETGET(float, "float")
  155. BIND_SETGET(double, "double")
  156. BIND_SETGET(bool, "bool")
  157. BIND_SETGET(void*, "void_p")
  158. #undef BIND_SETGET
  159. // patch VoidP
  160. type = vm->_t(VoidP::_type(vm));
  161. vm->bind_method<1>(type, "read_struct", [](VM* vm, ArgsView args){
  162. VoidP& self = _CAST(VoidP&, args[0]);
  163. int size = CAST(int, args[1]);
  164. return VAR_T(C99Struct, self.ptr, size);
  165. });
  166. vm->bind_method<1>(type, "write_struct", [](VM* vm, ArgsView args){
  167. VoidP& self = _CAST(VoidP&, args[0]);
  168. C99Struct& other = CAST(C99Struct&, args[1]);
  169. memcpy(self.ptr, other.p, other.size);
  170. return vm->None;
  171. });
  172. }
  173. void add_module_c(VM* vm){
  174. PyObject* mod = vm->new_module("c");
  175. #if PK_ENABLE_OS
  176. vm->bind_func<1>(mod, "malloc", [](VM* vm, ArgsView args){
  177. i64 size = CAST(i64, args[0]);
  178. return VAR(malloc(size));
  179. });
  180. vm->bind_func<1>(mod, "free", [](VM* vm, ArgsView args){
  181. void* p = CAST(void*, args[0]);
  182. free(p);
  183. return vm->None;
  184. });
  185. vm->bind_func<3>(mod, "memset", [](VM* vm, ArgsView args){
  186. void* p = CAST(void*, args[0]);
  187. memset(p, CAST(int, args[1]), CAST(size_t, args[2]));
  188. return vm->None;
  189. });
  190. vm->bind_func<3>(mod, "memcpy", [](VM* vm, ArgsView args){
  191. void* dst = CAST(void*, args[0]);
  192. void* src = CAST(void*, args[1]);
  193. i64 size = CAST(i64, args[2]);
  194. memcpy(dst, src, size);
  195. return vm->None;
  196. });
  197. #endif
  198. vm->bind_func<1>(mod, "sizeof", [](VM* vm, ArgsView args){
  199. const Str& type = CAST(Str&, args[0]);
  200. auto it = _refl_types.find(type.sv());
  201. if(it != _refl_types.end()) return VAR(it->second.size);
  202. vm->ValueError("not a valid c99 type");
  203. return vm->None;
  204. });
  205. VoidP::register_class(vm, mod);
  206. C99Struct::register_class(vm, mod);
  207. mod->attr().set("NULL", VAR_T(VoidP, nullptr));
  208. add_refl_type("void_p", sizeof(void*));
  209. PyObject* void_p_t = mod->attr("void_p");
  210. #define BIND_PRIMITIVE(T, name) \
  211. vm->bind_func<1>(mod, name "_", [](VM* vm, ArgsView args){ \
  212. T val = CAST(T, args[0]); \
  213. return VAR_T(C99Struct, &val, sizeof(T)); \
  214. }); \
  215. add_refl_type(name, sizeof(T)); \
  216. mod->attr().set(name "_p", void_p_t); \
  217. BIND_PRIMITIVE(char, "char")
  218. BIND_PRIMITIVE(unsigned char, "uchar")
  219. BIND_PRIMITIVE(short, "short")
  220. BIND_PRIMITIVE(unsigned short, "ushort")
  221. BIND_PRIMITIVE(int, "int")
  222. BIND_PRIMITIVE(unsigned int, "uint")
  223. BIND_PRIMITIVE(long, "long")
  224. BIND_PRIMITIVE(unsigned long, "ulong")
  225. BIND_PRIMITIVE(long long, "longlong")
  226. BIND_PRIMITIVE(unsigned long long, "ulonglong")
  227. BIND_PRIMITIVE(float, "float")
  228. BIND_PRIMITIVE(double, "double")
  229. BIND_PRIMITIVE(bool, "bool")
  230. // add array type
  231. CodeObject_ code = vm->compile(kPythonLibs["c"], "c.py", EXEC_MODE);
  232. vm->_exec(code, mod);
  233. }
  234. } // namespace pkpy