diff --git a/src/cffi.h b/src/cffi.h index 83019bbc..fa8a7f6e 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -379,7 +379,7 @@ struct NativeProxyFuncC final: NativeProxyFuncCBase { }; inline PyObject* _any_c_wrapper(VM* vm, ArgsView args){ - NativeProxyFuncCBase* pf = static_cast(lambda_get_userdata(args)._p); + NativeProxyFuncCBase* pf = lambda_get_userdata(args); return (*pf)(vm, args); } @@ -389,7 +389,7 @@ inline void bind_any_c_fp(VM* vm, PyObject* obj, Str name, T fp){ static_assert(std::is_pointer_v); auto proxy = new NativeProxyFuncC(fp); PyObject* func = VAR(NativeFunc(_any_c_wrapper, proxy->N, false)); - _CAST(NativeFunc&, func).userdata._p = proxy; + _CAST(NativeFunc&, func).set_userdata(proxy); obj->attr().set(name, func); } diff --git a/src/obj.h b/src/obj.h index 143b7cee..43ddeeb1 100644 --- a/src/obj.h +++ b/src/obj.h @@ -14,15 +14,6 @@ class VM; typedef PyObject* (*NativeFuncC)(VM*, ArgsView); typedef int (*LuaStyleFuncC)(VM*); -union UserData{ - void* _p; - void (*_fp)(void); - char _char; - int _int; - float _float; - bool _bool; -}; - struct NativeFunc { NativeFuncC f; int argc; // DONOT include self @@ -33,7 +24,22 @@ struct NativeFunc { // (-2) or (-1) depends on the calling convention LuaStyleFuncC _lua_f; - UserData userdata; + using UserData = char[32]; + UserData _userdata; + + template + void set_userdata(T data) { + static_assert(std::is_trivially_copyable_v); + static_assert(sizeof(T) <= sizeof(UserData)); + memcpy(_userdata, &data, sizeof(T)); + } + + template + T get_userdata() const { + static_assert(std::is_trivially_copyable_v); + static_assert(sizeof(T) <= sizeof(UserData)); + return reinterpret_cast(_userdata); + } NativeFunc(NativeFuncC f, int argc, bool method) : f(f), argc(argc), method(method), _lua_f(nullptr) {} PyObject* operator()(VM* vm, ArgsView args) const; @@ -391,18 +397,10 @@ struct Py_ final: PyObject { void _obj_gc_mark() override {} }; - template -T lambda_get_fp(ArgsView args){ - void (*f)(); - if(args[-1] != PY_NULL) f = OBJ_GET(NativeFunc, args[-1]).userdata._fp; - else f = OBJ_GET(NativeFunc, args[-2]).userdata._fp; - return reinterpret_cast(f); -} - -inline UserData& lambda_get_userdata(ArgsView args){ - if(args[-1] != PY_NULL) return OBJ_GET(NativeFunc, args[-1]).userdata; - else return OBJ_GET(NativeFunc, args[-2]).userdata; +inline T lambda_get_userdata(ArgsView args){ + if(args[-1] != PY_NULL) return OBJ_GET(NativeFunc, args[-1]).get_userdata(); + else return OBJ_GET(NativeFunc, args[-2]).get_userdata(); } diff --git a/src/vm.h b/src/vm.h index 07cc3310..50b5e888 100644 --- a/src/vm.h +++ b/src/vm.h @@ -338,9 +338,9 @@ public: void bind##name(Type type, PyObject* (*f)(VM*, PyObject*)){ \ _all_types[type].m##name = f; \ PyObject* nf = bind_method<0>(_t(type), #name, [](VM* vm, ArgsView args){ \ - return lambda_get_fp(args)(vm, args[0]); \ + return lambda_get_userdata(args)(vm, args[0]);\ }); \ - OBJ_GET(NativeFunc, nf).userdata._fp = reinterpret_cast(f); \ + OBJ_GET(NativeFunc, nf).set_userdata(f); \ } BIND_UNARY_SPECIAL(__repr__) @@ -361,10 +361,10 @@ public: PyObject* obj = _t(type); \ _all_types[type].m##name = f; \ PyObject* nf = bind_method<1>(obj, #name, [](VM* vm, ArgsView args){ \ - bool ok = lambda_get_fp(args)(vm, args[0], args[1]); \ + bool ok = lambda_get_userdata(args)(vm, args[0], args[1]); \ return ok ? vm->True : vm->False; \ }); \ - OBJ_GET(NativeFunc, nf).userdata._fp = reinterpret_cast(f); \ + OBJ_GET(NativeFunc, nf).set_userdata(f); \ } BIND_LOGICAL_SPECIAL(__eq__) @@ -381,10 +381,10 @@ public: void bind##name(Type type, PyObject* (*f)(VM*, PyObject*, PyObject*)){ \ PyObject* obj = _t(type); \ _all_types[type].m##name = f; \ - PyObject* nf = bind_method<1>(obj, #name, [](VM* vm, ArgsView args){ \ - return lambda_get_fp(args)(vm, args[0], args[1]); \ + PyObject* nf = bind_method<1>(obj, #name, [](VM* vm, ArgsView args){ \ + return lambda_get_userdata(args)(vm, args[0], args[1]); \ }); \ - OBJ_GET(NativeFunc, nf).userdata._fp = reinterpret_cast(f); \ + OBJ_GET(NativeFunc, nf).set_userdata(f); \ } BIND_BINARY_SPECIAL(__add__) @@ -408,29 +408,29 @@ public: PyObject* obj = _t(type); _all_types[type].m__getitem__ = f; PyObject* nf = bind_method<1>(obj, "__getitem__", [](VM* vm, ArgsView args){ - return lambda_get_fp(args)(vm, args[0], args[1]); + return lambda_get_userdata(args)(vm, args[0], args[1]); }); - OBJ_GET(NativeFunc, nf).userdata._fp = reinterpret_cast(f); + OBJ_GET(NativeFunc, nf).set_userdata(f); } void bind__setitem__(Type type, void (*f)(VM*, PyObject*, PyObject*, PyObject*)){ PyObject* obj = _t(type); _all_types[type].m__setitem__ = f; PyObject* nf = bind_method<2>(obj, "__setitem__", [](VM* vm, ArgsView args){ - lambda_get_fp(args)(vm, args[0], args[1], args[2]); + lambda_get_userdata(args)(vm, args[0], args[1], args[2]); return vm->None; }); - OBJ_GET(NativeFunc, nf).userdata._fp = reinterpret_cast(f); + OBJ_GET(NativeFunc, nf).set_userdata(f); } void bind__delitem__(Type type, void (*f)(VM*, PyObject*, PyObject*)){ PyObject* obj = _t(type); _all_types[type].m__delitem__ = f; PyObject* nf = bind_method<1>(obj, "__delitem__", [](VM* vm, ArgsView args){ - lambda_get_fp(args)(vm, args[0], args[1]); + lambda_get_userdata(args)(vm, args[0], args[1]); return vm->None; }); - OBJ_GET(NativeFunc, nf).userdata._fp = reinterpret_cast(f); + OBJ_GET(NativeFunc, nf).set_userdata(f); } bool py_equals(PyObject* lhs, PyObject* rhs){ @@ -1406,20 +1406,20 @@ inline void VM::bind__hash__(Type type, i64 (*f)(VM*, PyObject*)){ PyObject* obj = _t(type); _all_types[type].m__hash__ = f; PyObject* nf = bind_method<0>(obj, "__hash__", [](VM* vm, ArgsView args){ - i64 ret = lambda_get_fp(args)(vm, args[0]); + i64 ret = lambda_get_userdata(args)(vm, args[0]); return VAR(ret); }); - OBJ_GET(NativeFunc, nf).userdata._fp = reinterpret_cast(f); + OBJ_GET(NativeFunc, nf).set_userdata(f); } inline void VM::bind__len__(Type type, i64 (*f)(VM*, PyObject*)){ PyObject* obj = _t(type); _all_types[type].m__len__ = f; PyObject* nf = bind_method<0>(obj, "__len__", [](VM* vm, ArgsView args){ - i64 ret = lambda_get_fp(args)(vm, args[0]); + i64 ret = lambda_get_userdata(args)(vm, args[0]); return VAR(ret); }); - OBJ_GET(NativeFunc, nf).userdata._fp = reinterpret_cast(f); + OBJ_GET(NativeFunc, nf).set_userdata(f); }