-
Notifications
You must be signed in to change notification settings - Fork 87
Open
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