#pragma once #ifdef interface #undef interface #endif namespace steam { template struct argument_size_calculator final : std::integral_constant { }; template struct argument_size_calculator final : std::integral_constant::value + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1))> { }; class interface final { public: class method final { public: void* pointer = nullptr; size_t param_size = 0; }; class method_result final { public: std::string name; size_t param_size = 0; bool name_found = false; bool param_size_found = false; }; interface(); interface(void* interface_ptr); operator bool() const; template T invoke(const std::string& method_name, Args ... args) { if (!this->interface_ptr_) { throw std::runtime_error("Invalid interface pointer"); } const auto method_result = this->find_method(method_name); if (!method_result.pointer) { throw std::runtime_error("Unable to find desired method"); } constexpr size_t passed_argc = argument_size_calculator::value; if (passed_argc != method_result.param_size) { throw std::runtime_error("Invalid argument count"); } return reinterpret_cast(method_result.pointer)( this->interface_ptr_, args...); } template T invoke(const size_t table_entry, Args ... args) { if (!this->interface_ptr_) { throw std::runtime_error("Invalid interface pointer"); } return reinterpret_cast((*this->interface_ptr_)[table_entry])( this->interface_ptr_, args...); } private: void*** interface_ptr_; std::unordered_map methods_; method find_method(const std::string& name); method search_method(const std::string& name); method_result analyze_method(const void* method_ptr); bool is_rdata(void* pointer); }; }