From 6ba441a5fe998e6d82eb6e5575877e3a9a3778c1 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 26 Feb 2023 09:39:23 +0800 Subject: [PATCH] up --- src/cffi.h | 112 +++++++++++++++++++++++++++++---------------------- src/common.h | 2 +- tests/_c.py | 4 +- 3 files changed, 66 insertions(+), 52 deletions(-) diff --git a/src/cffi.h b/src/cffi.h index fb9a7d3e..bc5c57ad 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -6,8 +6,9 @@ struct CType{ PY_CLASS(c, _type) const char* name; // must be a literal - int size; - constexpr CType(const char name[], int size) : name(name), size(size) {} + const int size; + const int index; + constexpr CType(const char name[], int size, int index=-1) : name(name), size(size), index(index) {} static void _register(VM* vm, PyVar mod, PyVar type){ vm->bind_static_method<-1>(type, "__new__", CPP_NOT_IMPLEMENTED()); @@ -15,16 +16,21 @@ struct CType{ vm->bind_method<0>(type, "__repr__", [](VM* vm, pkpy::Args& args) { CType& self = vm->py_cast(args[0]); StrStream ss; - ss << ""; + ss << ""; return vm->PyStr(ss.str()); }); } }; constexpr CType kCTypes[] = { - CType("int8", 1), CType("int16", 2), CType("int32", 4), CType("int64", 8), - CType("uint8", 1), CType("uint16", 2), CType("uint32", 4), CType("uint64", 8), - CType("float32", 4), CType("float64", 8), CType("bool8", 1), CType("void", 0), + CType("char_", sizeof(char), 0), CType("int_", sizeof(int), 1), + CType("float_", sizeof(float), 2), CType("double_", sizeof(double), 3), + CType("bool_", sizeof(bool), 4), CType("void_", 0, 5), + CType("int8_", sizeof(int8_t), 6), CType("int16_", sizeof(int16_t), 7), + CType("int32_", sizeof(int32_t), 8), CType("int64_", sizeof(int64_t), 9), + CType("uint8_", sizeof(uint8_t), 10), CType("uint16_", sizeof(uint16_t), 11), + CType("uint32_", sizeof(uint32_t), 12), CType("uint64_", sizeof(uint64_t), 13), + // use macro here to do extension }; const int kCTypeCount = sizeof(kCTypes) / sizeof(CType); @@ -39,17 +45,15 @@ constexpr int ctype(const char name[]){ UNREACHABLE(); } -constexpr CType ctype_t(const char name[]){ - return kCTypes[ctype(name)]; -} +#define ctype_t(x) (kCTypes[ctype(x)]) struct Pointer{ PY_CLASS(c, _ptr) void* ptr; - CType _ctype; + CType _ctype; // base type - Pointer(void* ptr, CType ctype) : ptr(ptr), _ctype(ctype) {} + Pointer(void* ptr, CType _ctype) : ptr(ptr), _ctype(_ctype) {} static void _register(VM* vm, PyVar mod, PyVar type){ vm->bind_static_method<-1>(type, "__new__", CPP_NOT_IMPLEMENTED()); @@ -61,22 +65,26 @@ struct Pointer{ return vm->PyStr(ss.str()); }); + // https://docs.python.org/zh-cn/3/library/ctypes.html vm->bind_method<1>(type, "__getitem__", [](VM* vm, pkpy::Args& args) { Pointer& self = vm->py_cast(args[0]); i64 index = vm->PyInt_AS_C(args[1]); - switch(ctype(self._ctype.name)){ // TODO: optimize - case ctype("int8"): return vm->PyInt(((int8_t*)self.ptr)[index]); - case ctype("int16"): return vm->PyInt(((int16_t*)self.ptr)[index]); - case ctype("int32"): return vm->PyInt(((int32_t*)self.ptr)[index]); - case ctype("int64"): return vm->PyInt(((int64_t*)self.ptr)[index]); - case ctype("uint8"): return vm->PyInt(((uint8_t*)self.ptr)[index]); - case ctype("uint16"): return vm->PyInt(((uint16_t*)self.ptr)[index]); - case ctype("uint32"): return vm->PyInt(((uint32_t*)self.ptr)[index]); - case ctype("uint64"): return vm->PyInt(((uint64_t*)self.ptr)[index]); - case ctype("float32"): return vm->PyFloat(((float*)self.ptr)[index]); - case ctype("float64"): return vm->PyFloat(((double*)self.ptr)[index]); - case ctype("bool8"): return vm->PyBool(((bool*)self.ptr)[index]); - case ctype("void"): vm->TypeError("cannot index void*"); + switch(self._ctype.index){ + case ctype("char_"): return vm->PyInt(((char*)self.ptr)[index]); + case ctype("int_"): return vm->PyInt(((int*)self.ptr)[index]); + case ctype("float_"): return vm->PyFloat(((float*)self.ptr)[index]); + case ctype("double_"): return vm->PyFloat(((double*)self.ptr)[index]); + case ctype("bool_"): return vm->PyBool(((bool*)self.ptr)[index]); + case ctype("void_"): vm->TypeError("cannot index void*"); break; + case ctype("int8_"): return vm->PyInt(((int8_t*)self.ptr)[index]); + case ctype("int16_"): return vm->PyInt(((int16_t*)self.ptr)[index]); + case ctype("int32_"): return vm->PyInt(((int32_t*)self.ptr)[index]); + case ctype("int64_"): return vm->PyInt(((int64_t*)self.ptr)[index]); + case ctype("uint8_"): return vm->PyInt(((uint8_t*)self.ptr)[index]); + case ctype("uint16_"): return vm->PyInt(((uint16_t*)self.ptr)[index]); + case ctype("uint32_"): return vm->PyInt(((uint32_t*)self.ptr)[index]); + case ctype("uint64_"): return vm->PyInt(((uint64_t*)self.ptr)[index]); + // use macro here to do extension default: UNREACHABLE(); } return vm->None; @@ -85,29 +93,36 @@ struct Pointer{ vm->bind_method<2>(type, "__setitem__", [](VM* vm, pkpy::Args& args) { Pointer& self = vm->py_cast(args[0]); i64 index = vm->PyInt_AS_C(args[1]); - switch(ctype(self._ctype.name)){ // TODO: optimize - case ctype("int8"): ((int8_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; - case ctype("int16"): ((int16_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; - case ctype("int32"): ((int32_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; - case ctype("int64"): ((int64_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; - case ctype("uint8"): ((uint8_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; - case ctype("uint16"): ((uint16_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; - case ctype("uint32"): ((uint32_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; - case ctype("uint64"): ((uint64_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; - case ctype("float32"): ((float*)self.ptr)[index] = vm->PyFloat_AS_C(args[2]); break; - case ctype("float64"): ((double*)self.ptr)[index] = vm->PyFloat_AS_C(args[2]); break; - case ctype("bool8"): ((bool*)self.ptr)[index] = vm->PyBool_AS_C(args[2]); break; - case ctype("void"): vm->TypeError("cannot index void*"); + switch(self._ctype.index){ + case ctype("char_"): ((char*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("int_"): ((int*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("float_"): ((float*)self.ptr)[index] = vm->PyFloat_AS_C(args[2]); break; + case ctype("double_"): ((double*)self.ptr)[index] = vm->PyFloat_AS_C(args[2]); break; + case ctype("bool_"): ((bool*)self.ptr)[index] = vm->PyBool_AS_C(args[2]); break; + case ctype("void_"): vm->TypeError("cannot index void*"); break; + case ctype("int8_"): ((int8_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("int16_"): ((int16_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("int32_"): ((int32_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("int64_"): ((int64_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("uint8_"): ((uint8_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("uint16_"): ((uint16_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("uint32_"): ((uint32_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + case ctype("uint64_"): ((uint64_t*)self.ptr)[index] = vm->PyInt_AS_C(args[2]); break; + // use macro here to do extension default: UNREACHABLE(); } return vm->None; }); + + vm->bind_method<1>(type, "cast", [](VM* vm, pkpy::Args& args) { + Pointer& self = vm->py_cast(args[0]); + CType& ctype = vm->py_cast(args[1]); + return vm->new_object(self.ptr, ctype); + }); } template - inline T cast() noexcept { - return reinterpret_cast(ptr); - } + inline T cast() noexcept { return reinterpret_cast(ptr); } }; void add_module_c(VM* vm){ @@ -121,13 +136,7 @@ void add_module_c(VM* vm){ vm->bind_func<1>(mod, "malloc", [](VM* vm, pkpy::Args& args) { i64 size = vm->PyInt_AS_C(args[0]); - return vm->new_object(malloc(size), ctype_t("void")); - }); - - vm->bind_func<2>(mod, "cast", [](VM* vm, pkpy::Args& args) { - Pointer& self = vm->py_cast(args[0]); - CType& ctype = vm->py_cast(args[1]); - return vm->new_object(self.ptr, ctype); + return vm->new_object(malloc(size), ctype_t("void_")); }); vm->bind_func<1>(mod, "free", [](VM* vm, pkpy::Args& args) { @@ -160,10 +169,10 @@ void add_module_c(VM* vm){ vm->bind_func<1>(mod, "strdup", [ptr_t](VM* vm, pkpy::Args& args) { if(is_type(args[0], vm->tp_str)){ const Str& s = vm->PyStr_AS_C(args[0]); - return vm->new_object(strdup(s.c_str()), ctype_t("char")); + return vm->new_object(strdup(s.c_str()), ctype_t("char_")); }else if(is_type(args[0], OBJ_GET(Type, ptr_t))){ Pointer& p = vm->py_cast(args[0]); - return vm->new_object(strdup(p.cast()), ctype_t("char")); + return vm->new_object(strdup(p.cast()), ctype_t("char_")); }else{ vm->TypeError("strdup() argument must be 'str' or 'c._ptr'"); return vm->None; @@ -175,4 +184,9 @@ void add_module_c(VM* vm){ Pointer& p2 = vm->py_cast(args[1]); return vm->PyInt(strcmp(p1.cast(), p2.cast())); }); + + vm->bind_func<1>(mod, "strlen", [](VM* vm, pkpy::Args& args) { + Pointer& p = vm->py_cast(args[0]); + return vm->PyInt(strlen(p.cast())); + }); } \ No newline at end of file diff --git a/src/common.h b/src/common.h index f6b46405..bd8b1869 100644 --- a/src/common.h +++ b/src/common.h @@ -35,7 +35,7 @@ #define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!"); #endif -#define PK_VERSION "0.9.0" +#define PK_VERSION "0.9.1" #if defined(__EMSCRIPTEN__) || defined(__arm__) || defined(__i386__) typedef int32_t i64; diff --git a/tests/_c.py b/tests/_c.py index a112af4c..eb1a829b 100644 --- a/tests/_c.py +++ b/tests/_c.py @@ -1,7 +1,7 @@ from c import * -p = malloc(10 * sizeof(int32)) -p = cast(p, int32) +p = malloc(10 * sizeof(int_)) +p = p.cast(int_) for i in range(10): p[i] = i