cffi.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #pragma once
  2. #include "vm.h"
  3. namespace pkpy {
  4. struct CType{
  5. PY_CLASS(c, type_)
  6. const char* name; // must be a literal
  7. const int size;
  8. const int index;
  9. constexpr CType(const char name[], int size, int index) : name(name), size(size), index(index) {}
  10. static void _register(VM* vm, PyVar mod, PyVar type){
  11. vm->bind_static_method<-1>(type, "__new__", CPP_NOT_IMPLEMENTED());
  12. vm->bind_method<0>(type, "__repr__", [](VM* vm, Args& args) {
  13. CType& self = vm->_cast<CType>(args[0]);
  14. StrStream ss;
  15. ss << "<c._type '" << self.name << "' (" << self.size*8 << " bits)>";
  16. return py_var(vm, ss.str());
  17. });
  18. }
  19. };
  20. constexpr CType kCTypes[] = {
  21. CType("char_", sizeof(char), 0), CType("int_", sizeof(int), 1),
  22. CType("float_", sizeof(float), 2), CType("double_", sizeof(double), 3),
  23. CType("bool_", sizeof(bool), 4), CType("void_", 1, 5),
  24. CType("int8_", sizeof(int8_t), 6), CType("int16_", sizeof(int16_t), 7),
  25. CType("int32_", sizeof(int32_t), 8), CType("int64_", sizeof(int64_t), 9),
  26. CType("uint8_", sizeof(uint8_t), 10), CType("uint16_", sizeof(uint16_t), 11),
  27. CType("uint32_", sizeof(uint32_t), 12), CType("uint64_", sizeof(uint64_t), 13),
  28. CType("void_p_", sizeof(intptr_t), 14),
  29. // use macro here to do extension
  30. };
  31. const int kCTypeCount = sizeof(kCTypes) / sizeof(CType);
  32. constexpr int C_TYPE(const char name[]){
  33. for(int k=0; k<kCTypeCount; k++){
  34. const char* i = kCTypes[k].name;
  35. const char* j = name;
  36. while(*i && *j && *i == *j) { i++; j++;}
  37. if(*i == *j) return k;
  38. }
  39. UNREACHABLE();
  40. }
  41. #define C_TYPE_T(x) (kCTypes[C_TYPE(x)])
  42. struct Pointer{
  43. PY_CLASS(c, ptr_)
  44. void* ptr;
  45. CType ctype; // base type
  46. Pointer(void* ptr, CType ctype) : ptr(ptr), ctype(ctype) {}
  47. Pointer operator+(i64 offset) const {
  48. return Pointer((int8_t*)ptr + offset * ctype.size, ctype);
  49. }
  50. Pointer operator-(i64 offset) const {
  51. return Pointer((int8_t*)ptr - offset * ctype.size, ctype);
  52. }
  53. static void _register(VM* vm, PyVar mod, PyVar type){
  54. vm->bind_static_method<-1>(type, "__new__", CPP_NOT_IMPLEMENTED());
  55. vm->bind_method<0>(type, "__repr__", [](VM* vm, Args& args) {
  56. Pointer& self = vm->_cast<Pointer>(args[0]);
  57. StrStream ss;
  58. ss << "<" << self.ctype.name << "* at " << (i64)self.ptr << ">";
  59. return py_var(vm, ss.str());
  60. });
  61. vm->bind_method<1>(type, "__add__", [](VM* vm, Args& args) {
  62. Pointer& self = vm->_cast<Pointer>(args[0]);
  63. return vm->new_object<Pointer>(self + py_cast<i64>(vm, args[1]));
  64. });
  65. vm->bind_method<1>(type, "__sub__", [](VM* vm, Args& args) {
  66. Pointer& self = vm->_cast<Pointer>(args[0]);
  67. return vm->new_object<Pointer>(self - py_cast_v<i64>(vm, args[1]));
  68. });
  69. vm->bind_method<1>(type, "__eq__", [](VM* vm, Args& args) {
  70. Pointer& self = vm->_cast<Pointer>(args[0]);
  71. Pointer& other = vm->_cast<Pointer>(args[1]);
  72. return py_var(vm, self.ptr == other.ptr);
  73. });
  74. vm->bind_method<1>(type, "__ne__", [](VM* vm, Args& args) {
  75. Pointer& self = vm->_cast<Pointer>(args[0]);
  76. Pointer& other = vm->_cast<Pointer>(args[1]);
  77. return py_var(vm, self.ptr != other.ptr);
  78. });
  79. // https://docs.python.org/zh-cn/3/library/ctypes.html
  80. vm->bind_method<1>(type, "__getitem__", [](VM* vm, Args& args) {
  81. Pointer& self = vm->_cast<Pointer>(args[0]);
  82. i64 index = py_cast_v<i64>(vm, args[1]);
  83. return (self+index).get(vm);
  84. });
  85. vm->bind_method<2>(type, "__setitem__", [](VM* vm, Args& args) {
  86. Pointer& self = vm->_cast<Pointer>(args[0]);
  87. i64 index = py_cast_v<i64>(vm, args[1]);
  88. (self+index).set(vm, args[2]);
  89. return vm->None;
  90. });
  91. vm->bind_method<1>(type, "cast", [](VM* vm, Args& args) {
  92. Pointer& self = vm->_cast<Pointer>(args[0]);
  93. CType& ctype = vm->_cast<CType>(args[1]);
  94. return vm->new_object<Pointer>(self.ptr, ctype);
  95. });
  96. vm->bind_method<0>(type, "get", [](VM* vm, Args& args) {
  97. Pointer& self = vm->_cast<Pointer>(args[0]);
  98. return self.get(vm);
  99. });
  100. vm->bind_method<1>(type, "set", [](VM* vm, Args& args) {
  101. Pointer& self = vm->_cast<Pointer>(args[0]);
  102. self.set(vm, args[1]);
  103. return vm->None;
  104. });
  105. }
  106. template<typename T>
  107. inline T& ref() noexcept { return *reinterpret_cast<T*>(ptr); }
  108. template<typename TP>
  109. inline TP cast() noexcept {
  110. static_assert(std::is_pointer_v<TP>);
  111. return reinterpret_cast<TP>(ptr);
  112. }
  113. PyVar get(VM* vm){
  114. switch(ctype.index){
  115. case C_TYPE("char_"): return py_var(vm, ref<char>());
  116. case C_TYPE("int_"): return py_var(vm, ref<int>());
  117. case C_TYPE("float_"): return py_var(vm, ref<float>());
  118. case C_TYPE("double_"): return py_var(vm, ref<double>());
  119. case C_TYPE("bool_"): return py_var(vm, ref<bool>());
  120. case C_TYPE("void_"): vm->ValueError("cannot get void*"); break;
  121. case C_TYPE("int8_"): return py_var(vm, ref<int8_t>());
  122. case C_TYPE("int16_"): return py_var(vm, ref<int16_t>());
  123. case C_TYPE("int32_"): return py_var(vm, ref<int32_t>());
  124. case C_TYPE("int64_"): return py_var(vm, ref<int64_t>());
  125. case C_TYPE("uint8_"): return py_var(vm, ref<uint8_t>());
  126. case C_TYPE("uint16_"): return py_var(vm, ref<uint16_t>());
  127. case C_TYPE("uint32_"): return py_var(vm, ref<uint32_t>());
  128. case C_TYPE("uint64_"): return py_var(vm, ref<uint64_t>());
  129. case C_TYPE("void_p_"): return vm->new_object<Pointer>(ref<void*>(), C_TYPE_T("void_"));
  130. // use macro here to do extension
  131. default: UNREACHABLE();
  132. }
  133. return vm->None;
  134. }
  135. void set(VM* vm, const PyVar& val){
  136. switch(ctype.index){
  137. case C_TYPE("char_"): ref<char>() = py_cast_v<i64>(vm, val); break;
  138. case C_TYPE("int_"): ref<int>() = py_cast_v<i64>(vm, val); break;
  139. case C_TYPE("float_"): ref<float>() = py_cast_v<f64>(vm, val); break;
  140. case C_TYPE("double_"): ref<double>() = py_cast_v<f64>(vm, val); break;
  141. case C_TYPE("bool_"): ref<bool>() = py_cast_v<bool>(vm, val); break;
  142. case C_TYPE("void_"): vm->ValueError("cannot set void*"); break;
  143. case C_TYPE("int8_"): ref<int8_t>() = py_cast_v<i64>(vm, val); break;
  144. case C_TYPE("int16_"): ref<int16_t>() = py_cast_v<i64>(vm, val); break;
  145. case C_TYPE("int32_"): ref<int32_t>() = py_cast_v<i64>(vm, val); break;
  146. case C_TYPE("int64_"): ref<int64_t>() = py_cast_v<i64>(vm, val); break;
  147. case C_TYPE("uint8_"): ref<uint8_t>() = py_cast_v<i64>(vm, val); break;
  148. case C_TYPE("uint16_"): ref<uint16_t>() = py_cast_v<i64>(vm, val); break;
  149. case C_TYPE("uint32_"): ref<uint32_t>() = py_cast_v<i64>(vm, val); break;
  150. case C_TYPE("uint64_"): ref<uint64_t>() = py_cast_v<i64>(vm, val); break;
  151. case C_TYPE("void_p_"): ref<void*>() = vm->_cast<Pointer>(val).ptr; break;
  152. // use macro here to do extension
  153. default: UNREACHABLE();
  154. }
  155. }
  156. };
  157. struct StructMemberInfo {
  158. int offset;
  159. CType type;
  160. };
  161. struct StructMetaInfo {
  162. Str name;
  163. std::map<StrName, StructMemberInfo> members;
  164. };
  165. struct Point2{
  166. int x;
  167. int y;
  168. };
  169. static const StructMetaInfo _Point2_info = {
  170. "Point2",
  171. {
  172. {StrName("x"), {offsetof(Point2, x), C_TYPE_T("int_")}},
  173. {StrName("y"), {offsetof(Point2, y), C_TYPE_T("int_")}},
  174. }
  175. };
  176. struct Struct {
  177. PY_CLASS(c, struct_)
  178. const StructMetaInfo* info;
  179. int8_t* _data; // store any `struct`
  180. Struct(const StructMetaInfo* info, int8_t* data) : info(info), _data(data) {}
  181. Struct(){
  182. info = &_Point2_info;
  183. _data = new int8_t[sizeof(Point2)];
  184. }
  185. ~Struct(){ delete[] _data; }
  186. Pointer address(VM* vm, StrName name){
  187. auto it = info->members.find(name);
  188. if(it == info->members.end()) vm->AttributeError("struct " + info->name + " has no member " + name.str());
  189. const StructMemberInfo& info = it->second;
  190. return {_data+info.offset, info.type};
  191. }
  192. PyVarOrNull __getattr__(VM* vm, StrName name){
  193. return address(vm, name).get(vm);
  194. }
  195. void __setattr__(VM* vm, StrName name, const PyVar& val){
  196. address(vm, name).set(vm, val);
  197. }
  198. static void _register(VM* vm, PyVar mod, PyVar type){
  199. vm->bind_static_method<-1>(type, "__new__", [](VM* vm, Args& args) {
  200. return vm->new_object<Struct>();
  201. });
  202. vm->bind_method<0>(type, "__repr__", [](VM* vm, Args& args) {
  203. Struct& self = vm->_cast<Struct>(args[0]);
  204. StrStream ss;
  205. ss << self.info->name << "(" << ")";
  206. return py_var(vm, ss.str());
  207. });
  208. }
  209. };
  210. void add_module_c(VM* vm){
  211. PyVar mod = vm->new_module("c");
  212. PyVar ptr_t = vm->register_class<Pointer>(mod);
  213. vm->register_class<CType>(mod);
  214. vm->register_class<Struct>(mod);
  215. for(int i=0; i<kCTypeCount; i++){
  216. vm->setattr(mod, kCTypes[i].name, vm->new_object<CType>(kCTypes[i]));
  217. }
  218. vm->setattr(mod, "nullptr", vm->new_object<Pointer>(nullptr, C_TYPE_T("void_")));
  219. vm->bind_func<1>(mod, "malloc", [](VM* vm, Args& args) {
  220. i64 size = py_cast_v<i64>(vm, args[0]);
  221. return vm->new_object<Pointer>(malloc(size), C_TYPE_T("void_"));
  222. });
  223. vm->bind_func<1>(mod, "free", [](VM* vm, Args& args) {
  224. Pointer& self = vm->_cast<Pointer>(args[0]);
  225. free(self.ptr);
  226. return vm->None;
  227. });
  228. vm->bind_func<1>(mod, "sizeof", [](VM* vm, Args& args) {
  229. CType& ctype = vm->_cast<CType>(args[0]);
  230. return py_var(vm, ctype.size);
  231. });
  232. vm->bind_func<3>(mod, "memcpy", [](VM* vm, Args& args) {
  233. Pointer& dst = vm->_cast<Pointer>(args[0]);
  234. Pointer& src = vm->_cast<Pointer>(args[1]);
  235. i64 size = py_cast_v<i64>(vm, args[2]);
  236. memcpy(dst.ptr, src.ptr, size);
  237. return vm->None;
  238. });
  239. vm->bind_func<3>(mod, "memset", [](VM* vm, Args& args) {
  240. Pointer& dst = vm->_cast<Pointer>(args[0]);
  241. i64 val = py_cast_v<i64>(vm, args[1]);
  242. i64 size = py_cast_v<i64>(vm, args[2]);
  243. memset(dst.ptr, (int)val, size);
  244. return vm->None;
  245. });
  246. vm->bind_func<1>(mod, "strdup", [ptr_t](VM* vm, Args& args) {
  247. if(is_type(args[0], vm->tp_str)){
  248. const Str& s = py_cast<Str>(vm, args[0]);
  249. return vm->new_object<Pointer>(strdup(s.c_str()), C_TYPE_T("char_"));
  250. }else if(is_type(args[0], OBJ_GET(Type, ptr_t))){
  251. Pointer& p = vm->_cast<Pointer>(args[0]);
  252. return vm->new_object<Pointer>(strdup(p.cast<char*>()), C_TYPE_T("char_"));
  253. }else{
  254. vm->TypeError("strdup() argument must be 'str' or 'char*'");
  255. return vm->None;
  256. }
  257. });
  258. vm->bind_func<2>(mod, "strcmp", [](VM* vm, Args& args) {
  259. Pointer& p1 = vm->_cast<Pointer>(args[0]);
  260. Pointer& p2 = vm->_cast<Pointer>(args[1]);
  261. return py_var(vm, strcmp(p1.cast<char*>(), p2.cast<char*>()));
  262. });
  263. vm->bind_func<1>(mod, "strlen", [](VM* vm, Args& args) {
  264. Pointer& p = vm->_cast<Pointer>(args[0]);
  265. return py_var(vm, strlen(p.cast<char*>()));
  266. });
  267. }
  268. } // namespace pkpy