allow hook getunboundmethod

This commit is contained in:
blueloveTH 2025-07-17 11:17:24 +08:00
parent 7016a8780c
commit 5799af3fd7
4 changed files with 31 additions and 18 deletions

View File

@ -16,9 +16,10 @@ typedef struct py_TypeInfo {
bool is_python; // is it a python class? (not derived from c object) bool is_python; // is it a python class? (not derived from c object)
bool is_sealed; // can it be subclassed? bool is_sealed; // can it be subclassed?
bool (*getattribute)(py_Ref self, py_Name name); bool (*getattribute)(py_Ref self, py_Name name) PY_RAISE PY_RETURN;
bool (*setattribute)(py_Ref self, py_Name name, py_Ref val); bool (*setattribute)(py_Ref self, py_Name name, py_Ref val) PY_RAISE PY_RETURN;
bool (*delattribute)(py_Ref self, py_Name name); bool (*delattribute)(py_Ref self, py_Name name) PY_RAISE;
bool (*getunboundmethod)(py_Ref self, py_Name name) PY_RETURN;
py_TValue annotations; py_TValue annotations;
py_Dtor dtor; // destructor for this type, NULL if no dtor py_Dtor dtor; // destructor for this type, NULL if no dtor

View File

@ -33,6 +33,7 @@ typedef struct py_TValue {
py_Type type; py_Type type;
bool is_ptr; bool is_ptr;
int extra; int extra;
union { union {
int64_t _i64; int64_t _i64;
char _chars[16]; char _chars[16];
@ -372,9 +373,11 @@ PK_API bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE PY_RETURN;
/// Set attribute hooks for the given type. /// Set attribute hooks for the given type.
PK_API void py_tphookattributes(py_Type type, PK_API void py_tphookattributes(py_Type type,
bool (*getattribute)(py_Ref self, py_Name name), bool (*getattribute)(py_Ref self, py_Name name) PY_RAISE PY_RETURN,
bool (*setattribute)(py_Ref self, py_Name name, py_Ref val), bool (*setattribute)(py_Ref self, py_Name name, py_Ref val)
bool (*delattribute)(py_Ref self, py_Name name)); PY_RAISE PY_RETURN,
bool (*delattribute)(py_Ref self, py_Name name) PY_RAISE,
bool (*getunboundmethod)(py_Ref self, py_Name name) PY_RETURN);
/// Check if the object is an instance of the given type exactly. /// Check if the object is an instance of the given type exactly.
/// Raise `TypeError` if the check fails. /// Raise `TypeError` if the check fails.

View File

@ -159,10 +159,12 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, vo
void py_tphookattributes(py_Type type, void py_tphookattributes(py_Type type,
bool (*getattribute)(py_Ref self, py_Name name), bool (*getattribute)(py_Ref self, py_Name name),
bool (*setattribute)(py_Ref self, py_Name name, py_Ref val), bool (*setattribute)(py_Ref self, py_Name name, py_Ref val),
bool (*delattribute)(py_Ref self, py_Name name)) { bool (*delattribute)(py_Ref self, py_Name name),
bool (*getunboundmethod)(py_Ref self, py_Name name)) {
assert(type); assert(type);
py_TypeInfo* ti = pk_typeinfo(type); py_TypeInfo* ti = pk_typeinfo(type);
ti->getattribute = getattribute; ti->getattribute = getattribute;
ti->setattribute = setattribute; ti->setattribute = setattribute;
ti->delattribute = delattribute; ti->delattribute = delattribute;
ti->getunboundmethod = getunboundmethod;
} }

View File

@ -45,17 +45,11 @@ void py_initialize() {
pk_initialized = true; pk_initialized = true;
} }
void* py_malloc(size_t size) { void* py_malloc(size_t size) { return PK_MALLOC(size); }
return PK_MALLOC(size);
}
void* py_realloc(void* ptr, size_t size) { void* py_realloc(void* ptr, size_t size) { return PK_REALLOC(ptr, size); }
return PK_REALLOC(ptr, size);
}
void py_free(void* ptr) { void py_free(void* ptr) { PK_FREE(ptr); }
PK_FREE(ptr);
}
py_GlobalRef py_True() { return &_True; } py_GlobalRef py_True() { return &_True; }
@ -233,7 +227,20 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
self_bak = *self; self_bak = *self;
} }
py_Ref cls_var = py_tpfindname(type, name); py_TypeInfo* ti = pk_typeinfo(type);
if(ti->getunboundmethod) {
bool ok = ti->getunboundmethod(self, name);
if(ok) {
self[0] = *py_retval();
self[1] = self_bak;
return true;
} else {
return false;
}
}
py_Ref cls_var = pk_tpfindname(ti, name);
if(cls_var != NULL) { if(cls_var != NULL) {
switch(cls_var->type) { switch(cls_var->type) {
case tp_function: case tp_function:
@ -248,7 +255,7 @@ bool pk_loadmethod(py_StackRef self, py_Name name) {
break; break;
case tp_classmethod: case tp_classmethod:
self[0] = *py_getslot(cls_var, 0); self[0] = *py_getslot(cls_var, 0);
self[1] = pk_typeinfo(type)->self; self[1] = ti->self;
break; break;
default: c11__unreachable(); default: c11__unreachable();
} }