-
Couldn't load subscription status.
- Fork 91
Open
@axhlzy
Description
ps:本来想直接提交pr的,但是看到你的项目好像转移到另一个github账号了,就直接这样给你反馈吧
很多时候我想使用unity obj直接去调用obj下的方法,然后看了一下你的源码,发现有几处可以优化一下
这里举例说明一下我想实现的效果:
// [-]Assembly-CSharp @ 0x78eebf5220 // [-]Assembly-CSharp.dll @ 0x79806bed60 | C:433 // [-]IronSourceManager @ 0x77a03b2900 | M:90 | F:13 // [-]public Boolean ShowReward(UnityEvent onCompleted, UnityEvent onFailed) @ MI: 0x77a03d30a0 & MP: 0x788db69e28 & RP: 0xbe5e28 // [-]onCompleted | type: 0x788ea15c28 | @ class:0x78eedf6540 | UnityEngine.Events.UnityEvent // [-]onFailed | type: 0x788ea15c28 | @ class:0x78eedf6540 | UnityEngine.Events.UnityEvent // [-]_RET_ | type: 0x788e9f97b8 | @ class:0x78eede4300 | System.Boolean static auto Class_IronSourceManager = UnityResolve::Get("Assembly-CSharp.dll") ->Get("IronSourceManager"); for (auto *method : Class_IronSourceManager->methods) { logd("IronSourceManager %s", method->name.c_str()); if (method->name == "ShowReward") { HookManager::registerHook(method->function, *[](void *instance, UnityResolve::UnityType::Object *onCompleted, UnityResolve::UnityType::Object *onFailed) { logd("called IronSourceManager ShowReward"); // ------------------------------------------------------ //| Found 6 Methods in class: UnityEvent @ 0x78f02ec2c0 | // ------------------------------------------------------ //[*] 0x789e322ef0 ---> 0x7890926bd8 ---> 0xa53bd8 | public Void .ctor() //[*] 0x789e322f40 ---> 0x7890926cb4 ---> 0xa53cb4 | public Void AddListener(UnityAction call) //[*] 0x789e323080 ---> 0x7890926ff4 ---> 0xa53ff4 | public Void Invoke() //[*] 0x789e322f90 ---> 0x7890926d6c ---> 0xa53d6c | protected override MethodInfo FindMethod_Impl(String name, Type targetObjType) //[*] 0x789e323030 ---> 0x7890926cf0 ---> 0xa53cf0 | private static BaseInvokableCall GetDelegate(UnityAction action) //[*] 0x789e322fe0 ---> 0x7890926f84 ---> 0xa53f84 | internal override BaseInvokableCall GetDelegate(Object target, MethodInfo theFunction) onCompleted->invokeMethod<void>("Invoke"); }); } });
我希望通过obj直接去调用obj(所属类"UnityEngine.Events.UnityEvent")下面的invoke方法,按照你现在的代码逻辑还得去获取一遍,就不太方便,我这里为obj多封装了两个函数
struct Object { union { void *klass{nullptr}; void *vtable; } Il2CppClass; struct MonitorData *monitor{nullptr}; auto GetType() -> CsType * { static Method *method; if (!method) method = Get("mscorlib.dll")->Get("Object", "System")->Get<Method>("GetType"); if (method) return method->Invoke<CsType *>(this); return nullptr; } auto ToString() -> String * { static Method *method; if (!method) method = Get("mscorlib.dll")->Get("Object", "System")->Get<Method>("ToString"); if (method) return method->Invoke<String *>(this); return {}; } int GetHashCode() { static Method *method; if (!method) method = Get("mscorlib.dll")->Get("Object", "System")->Get<Method>("GetHashCode"); if (method) return method->Invoke<int>(this); return 0; } [[nodiscard]] auto tryMethod(const std::string &name, const std::vector<std::string> &args = {}) const { UnityResolve::Class clazz(this->Il2CppClass.klass); return clazz.Get<UnityResolve::Method>(name, args); } template<typename T> T invokeMethod(const std::string &name, const std::vector<std::string> &args = {}, const std::vector<void *> ¶ms = {}) { auto method = tryMethod(name, args); if (!method) { if constexpr (!std::is_void_v<T>) return T{}; else return; } if constexpr (std::is_void_v<T>) { method->Invoke<void>(this, params); } else { return method->Invoke<T>(this, params); } } };
以及修改了一下UnityResolve::Class的构造函数
struct Class final { void *address{}; std::string name; std::string parent; std::string namespaze; std::vector<Field *> fields; std::vector<Method *> methods; void *objType{}; Class()= default; explicit Class(void* pClass){ this->address = pClass; this->name = Invoke<const char *>("il2cpp_class_get_name", pClass); if (const auto pPClass = Invoke<void *>("il2cpp_class_get_parent", pClass)) this->parent = Invoke<const char *>("il2cpp_class_get_name", pPClass); this->namespaze = Invoke<const char *>("il2cpp_class_get_namespace", pClass); ForeachFields(this, pClass); ForeachMethod(this, pClass); void *i_class; void *iter{}; do { if ((i_class = Invoke<void *>("il2cpp_class_get_interfaces", pClass, &iter))) { ForeachFields(this, i_class); ForeachMethod(this, i_class); } } while (i_class); } ...... }
这样一来我们就可以直接方便的去访问类实例下面的函数
总的来说,我是觉得他不应该一开始就遍历完了,然后就写"死了",这样的操作方法多了性能表现很差不说而且也不够灵活
而是需要的时候去构造Class(ptr)得到一个解析好的class,需要什么构造什么 ...
其实就是内存地址和类型的随时任意的转换,这样才更像是一个灵活的工具
Metadata
Metadata
Assignees
Labels
No labels