mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 12:30:19 +00:00
up
This commit is contained in:
parent
37c4f1ee4c
commit
6ba441a5fe
112
src/cffi.h
112
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<CType>(args[0]);
|
||||
StrStream ss;
|
||||
ss << "<c._type '" << self.name << "'>";
|
||||
ss << "<c._type '" << self.name << "' (" << self.size*8 << " bits)>";
|
||||
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<Pointer>(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<Pointer>(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<Pointer>(args[0]);
|
||||
CType& ctype = vm->py_cast<CType>(args[1]);
|
||||
return vm->new_object<Pointer>(self.ptr, ctype);
|
||||
});
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T cast() noexcept {
|
||||
return reinterpret_cast<T>(ptr);
|
||||
}
|
||||
inline T cast() noexcept { return reinterpret_cast<T>(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<Pointer>(malloc(size), ctype_t("void"));
|
||||
});
|
||||
|
||||
vm->bind_func<2>(mod, "cast", [](VM* vm, pkpy::Args& args) {
|
||||
Pointer& self = vm->py_cast<Pointer>(args[0]);
|
||||
CType& ctype = vm->py_cast<CType>(args[1]);
|
||||
return vm->new_object<Pointer>(self.ptr, ctype);
|
||||
return vm->new_object<Pointer>(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<Pointer>(strdup(s.c_str()), ctype_t("char"));
|
||||
return vm->new_object<Pointer>(strdup(s.c_str()), ctype_t("char_"));
|
||||
}else if(is_type(args[0], OBJ_GET(Type, ptr_t))){
|
||||
Pointer& p = vm->py_cast<Pointer>(args[0]);
|
||||
return vm->new_object<Pointer>(strdup(p.cast<char*>()), ctype_t("char"));
|
||||
return vm->new_object<Pointer>(strdup(p.cast<char*>()), 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<Pointer>(args[1]);
|
||||
return vm->PyInt(strcmp(p1.cast<char*>(), p2.cast<char*>()));
|
||||
});
|
||||
|
||||
vm->bind_func<1>(mod, "strlen", [](VM* vm, pkpy::Args& args) {
|
||||
Pointer& p = vm->py_cast<Pointer>(args[0]);
|
||||
return vm->PyInt(strlen(p.cast<char*>()));
|
||||
});
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user