This commit is contained in:
blueloveTH 2023-05-13 20:32:15 +08:00
parent de45471a9d
commit a2caa487ab
3 changed files with 190 additions and 15 deletions

View File

@ -73,5 +73,6 @@ if os.path.exists("/mnt/e/PainterEngine/project/pocketpy.h"):
shutil.copy("amalgamated/pocketpy.h", "/mnt/e/PainterEngine/project/pocketpy.h")
shutil.copy("src/easing.pyi", "/mnt/e/PainterEngine/game/easing.pyi")
shutil.copy("src/linalg.pyi", "/mnt/e/PainterEngine/game/linalg.pyi")
shutil.copy("src/c.pyi", "/mnt/e/PainterEngine/game/c.pyi")

36
src/c.pyi Normal file
View File

@ -0,0 +1,36 @@
from typing import overload
def malloc(size: int) -> 'void_p': ...
def free(ptr: 'void_p') -> None: ...
def sizeof(type: str) -> int: ...
class void_p:
def __add__(self, i: int) -> 'void_p': ...
def __sub__(self, i: int) -> 'void_p': ...
def __eq__(self, other: 'void_p') -> bool: ...
def __ne__(self, other: 'void_p') -> bool: ...
def char(self) -> int: ...
def uchar(self) -> int: ...
def short(self) -> int: ...
def ushort(self) -> int: ...
def int(self) -> int: ...
def uint(self) -> int: ...
def long(self) -> int: ...
def ulong(self) -> int: ...
def longlong(self) -> int: ...
def ulonglong(self) -> int: ...
def float(self) -> float: ...
def double(self) -> float: ...
def bool(self) -> bool: ...
def void_p(self) -> 'void_p': ...
def get_base_offset(self) -> int: ...
@overload
def set_base_offset(self, offset: int) -> None: ...
@overload
def set_base_offset(self, offset: str) -> None: ...
class struct:
def address(self) -> 'void_p': ...
def copy(self) -> 'struct': ...

View File

@ -29,13 +29,36 @@ namespace pkpy {
#define VAR_T(T, ...) vm->heap.gcnew<T>(T::_type(vm), T(__VA_ARGS__))
inline static int c99_sizeof(VM* vm, const Str& type){
static const std::map<Str, i64> c99_sizes = {
{"char", sizeof(char)},
{"uchar", sizeof(unsigned char)},
{"short", sizeof(short)},
{"ushort", sizeof(unsigned short)},
{"int", sizeof(int)},
{"uint", sizeof(unsigned int)},
{"long", sizeof(long)},
{"ulong", sizeof(unsigned long)},
{"longlong", sizeof(long long)},
{"ulonglong", sizeof(unsigned long long)},
{"float", sizeof(float)},
{"double", sizeof(double)},
{"bool", sizeof(bool)},
{"void_p", sizeof(void*)}
};
auto it = c99_sizes.find(type);
if(it != c99_sizes.end()) return it->second;
vm->ValueError("not a valid c99 type");
return 0;
}
struct VoidP{
PY_CLASS(VoidP, c, void_p)
void* ptr;
VoidP(void* ptr): ptr(ptr){}
VoidP(): ptr(nullptr){}
int base_offset;
VoidP(void* ptr): ptr(ptr), base_offset(1){}
VoidP(): ptr(nullptr), base_offset(1){}
static void _register(VM* vm, PyObject* mod, PyObject* type){
vm->bind_default_constructor<VoidP>(type);
@ -43,32 +66,140 @@ struct VoidP{
vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
std::stringstream ss;
ss << "<void* at " << self.ptr << ">";
ss << "<void* at " << self.ptr;
if(self.base_offset != 1) ss << ", base_offset=" << self.base_offset;
ss << ">";
return VAR(ss.str());
});
vm->bind_method<1>(type, "__eq__", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
VoidP& other = CAST(VoidP&, args[1]);
return VAR(self.ptr == other.ptr && self.base_offset == other.base_offset);
});
vm->bind_method<1>(type, "__ne__", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
VoidP& other = CAST(VoidP&, args[1]);
return VAR(self.ptr != other.ptr || self.base_offset != other.base_offset);
});
vm->bind_method<1>(type, "set_base_offset", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
if(is_non_tagged_type(args[1], vm->tp_str)){
const Str& type = _CAST(Str&, args[1]);
self.base_offset = c99_sizeof(vm, type);
}else{
self.base_offset = CAST(int, args[1]);
}
return vm->None;
});
vm->bind_method<0>(type, "get_base_offset", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
return VAR(self.base_offset);
});
vm->bind_method<1>(type, "__add__", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
i64 offset = CAST(i64, args[1]);
return VAR_T(VoidP, (char*)self.ptr + offset * self.base_offset);
});
vm->bind_method<1>(type, "__sub__", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
i64 offset = CAST(i64, args[1]);
return VAR_T(VoidP, (char*)self.ptr - offset * self.base_offset);
});
#define BIND_SETGET(T, name) \
vm->bind_method<0>(type, name, [](VM* vm, ArgsView args){ \
VoidP& self = _CAST(VoidP&, args[0]); \
return VAR(*(T*)self.ptr); \
}); \
vm->bind_method<1>(type, "set_" name, [](VM* vm, ArgsView args){ \
VoidP& self = _CAST(VoidP&, args[0]); \
*(T*)self.ptr = CAST(T, args[1]); \
return vm->None; \
});
BIND_SETGET(char, "char")
BIND_SETGET(unsigned char, "uchar")
BIND_SETGET(short, "short")
BIND_SETGET(unsigned short, "ushort")
BIND_SETGET(int, "int")
BIND_SETGET(unsigned int, "uint")
BIND_SETGET(long, "long")
BIND_SETGET(unsigned long, "ulong")
BIND_SETGET(long long, "longlong")
BIND_SETGET(unsigned long long, "ulonglong")
BIND_SETGET(float, "float")
BIND_SETGET(double, "double")
BIND_SETGET(bool, "bool")
vm->bind_method<0>(type, "void_p", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
return VAR_T(VoidP, *(void**)self.ptr);
});
vm->bind_method<1>(type, "set_void_p", [](VM* vm, ArgsView args){
VoidP& self = _CAST(VoidP&, args[0]);
VoidP& other = CAST(VoidP&, args[0]);
self.ptr = other.ptr;
return vm->None;
});
}
};
struct PlainOldData{
PY_CLASS(PlainOldData, c, pod)
struct Struct{
PY_CLASS(Struct, c, struct)
static constexpr int INLINE_SIZE = 32;
char _inlined[INLINE_SIZE];
char* p;
template<typename T>
PlainOldData(const T& data){
Struct(const T& data){
static_assert(std::is_pod_v<T>);
p = new char[sizeof(T)];
memcpy(p, &data, sizeof(T));
if(sizeof(T) <= INLINE_SIZE){
memcpy(_inlined, &data, sizeof(T));
p = _inlined;
}else{
p = (char*)malloc(sizeof(T));
memcpy(p, &data, sizeof(T));
}
}
PlainOldData(): p(nullptr){}
~PlainOldData(){ delete[] p; }
Struct() { p = _inlined; }
~Struct(){ if(p!=_inlined) free(p); }
Struct(const Struct& other){
if(other.p == other._inlined){
memcpy(_inlined, other._inlined, INLINE_SIZE);
p = _inlined;
}else{
p = (char*)malloc(sizeof(other));
memcpy(p, other.p, sizeof(other));
}
}
static void _register(VM* vm, PyObject* mod, PyObject* type){
vm->bind_default_constructor<PlainOldData>(type);
vm->bind_default_constructor<Struct>(type);
vm->bind_method<0>(type, "address", [](VM* vm, ArgsView args){
Struct& self = _CAST(Struct&, args[0]);
return VAR_T(VoidP, self.p);
});
vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
const Struct& self = _CAST(Struct&, args[0]);
return VAR_T(Struct, self);
});
}
};
static_assert(sizeof(Py_<Struct>) <= 64);
inline PyObject* py_var(VM* vm, void* p){
return VAR_T(VoidP, p);
}
@ -87,13 +218,13 @@ T to_void_p(VM* vm, PyObject* var){
template<typename T>
T to_plain_old_data(VM* vm, PyObject* var){
static_assert(std::is_pod_v<T>);
PlainOldData& pod = CAST(PlainOldData&, var);
Struct& pod = CAST(Struct&, var);
return *reinterpret_cast<T*>(pod.p);
}
template<typename T>
std::enable_if_t<std::is_pod_v<T> && !std::is_pointer_v<T>, PyObject*> py_var(VM* vm, const T& data){
return VAR_T(PlainOldData, data);
return VAR_T(Struct, data);
}
/*****************************************************************/
struct NativeProxyFuncCBase {
@ -160,8 +291,15 @@ inline void add_module_c(VM* vm){
return vm->None;
});
vm->bind_func<1>(mod, "sizeof", [](VM* vm, ArgsView args){
const Str& type = CAST(Str&, args[0]);
i64 size = c99_sizeof(vm, type);
return VAR(size);
});
VoidP::register_class(vm, mod);
PlainOldData::register_class(vm, mod);
Struct::register_class(vm, mod);
mod->attr().set("NULL", VAR_T(VoidP, nullptr));
}
} // namespace pkpy