diff --git a/app/src/main/cpp/skyline/services/am/proxy/IApplicationProxy.h b/app/src/main/cpp/skyline/services/am/proxy/IApplicationProxy.h index 47b713f3..f3cfa6f8 100644 --- a/app/src/main/cpp/skyline/services/am/proxy/IApplicationProxy.h +++ b/app/src/main/cpp/skyline/services/am/proxy/IApplicationProxy.h @@ -20,9 +20,6 @@ namespace skyline::service::am { */ Result GetApplicationFunctions(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); - //#undef SFUNC_BASE - //#define SFUNC_BASE(id, Class, BaseClass, Function) std::pair, std::string_view>>{id, {&CallBaseFunction, #Function}} - SERVICE_DECL( SFUNC_BASE(0x0, IApplicationProxy, BaseProxy, GetCommonStateGetter), SFUNC_BASE(0x1, IApplicationProxy, BaseProxy, GetSelfController), diff --git a/app/src/main/cpp/skyline/services/base_service.cpp b/app/src/main/cpp/skyline/services/base_service.cpp index 4f2c64a4..fa9f7125 100644 --- a/app/src/main/cpp/skyline/services/base_service.cpp +++ b/app/src/main/cpp/skyline/services/base_service.cpp @@ -19,18 +19,18 @@ namespace skyline::service { } Result service::BaseService::HandleRequest(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - std::pair, std::string_view> function; + ServiceFunctionDescriptor function; try { function = GetServiceFunction(request.payload->value); - state.logger->DebugNoPrefix("Service: {} @ {}", function.second, GetName()); + state.logger->DebugNoPrefix("Service: {}", function.name); } catch (const std::out_of_range &) { state.logger->Warn("Cannot find function in service '{0}': 0x{1:X} ({1})", GetName(), static_cast(request.payload->value)); return {}; } try { - return function.first(session, request, response); + return function(session, request, response); } catch (const std::exception &e) { - throw exception("{} (Service: {} @ {})", e.what(), function.second, GetName()); + throw exception("{} (Service: {})", e.what(), function.name); } } } diff --git a/app/src/main/cpp/skyline/services/base_service.h b/app/src/main/cpp/skyline/services/base_service.h index 6f2bd7cd..bb3c094a 100644 --- a/app/src/main/cpp/skyline/services/base_service.h +++ b/app/src/main/cpp/skyline/services/base_service.h @@ -5,14 +5,25 @@ #include -#define SFUNC(id, Class, Function) std::pair, std::string_view>>{id, {&Class::Function, #Function}} -#define SFUNC_BASE(id, Class, BaseClass, Function) std::pair, std::string_view>>{id, {&CallBaseFunction, #Function}} +#define SERVICE_STRINGIFY(string) #string +#define SFUNC(id, Class, Function) std::pair>{id, {&Class::Function, SERVICE_STRINGIFY(Class::Function)}} +#define SFUNC_BASE(id, Class, BaseClass, Function) std::pair>{id, {&Class::CallBaseFunction, SERVICE_STRINGIFY(Class::Function)}} #define SERVICE_DECL_AUTO(name, value) decltype(value) name = value -#define SERVICE_DECL(...) \ -SERVICE_DECL_AUTO(functions, frz::make_unordered_map({__VA_ARGS__})); \ -std::pair, std::string_view> GetServiceFunction(u32 id) override { \ - auto& function{functions.at(id)}; \ - return std::make_pair(std::bind(function.first, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), function.second); \ +#define SERVICE_DECL(...) \ +private: \ +template \ +Result CallBaseFunction(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { \ + return (static_cast(this)->*BaseFunction)(session, request, response); \ +} \ +SERVICE_DECL_AUTO(functions, frz::make_unordered_map({__VA_ARGS__})); \ +protected: \ +ServiceFunctionDescriptor GetServiceFunction(u32 id) override { \ + auto& function{functions.at(id)}; \ + return ServiceFunctionDescriptor{ \ + reinterpret_cast(this), \ + reinterpret_cast(function.first), \ + function.second \ + }; \ } #define SRVREG(class, ...) std::make_shared(state, manager, ##__VA_ARGS__) @@ -37,10 +48,20 @@ namespace skyline::service { const DeviceState &state; ServiceManager &manager; - template - static constexpr Result CallBaseFunction(Class *clazz, type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - return (static_cast(clazz)->*BaseFunction)(session, request, response); - } + class DerivedService; //!< A placeholder derived class which is used for class function semantics + + /** + * @brief A per-service-function descriptor with it's name and a function pointer to it + */ + struct ServiceFunctionDescriptor { + DerivedService *clazz; //!< A pointer to the class that this was derived from, it's used as the 'this' pointer for the function + Result (DerivedService::*function)(type::KSession &, ipc::IpcRequest &, ipc::IpcResponse &); //!< A function pointer to a HLE implementation of the service function + const char *name; //!< A pointer to a static string in the format "Class::Function" for the specific service class/function + + constexpr Result operator()(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + return (clazz->*function)(session, request, response); + } + }; public: BaseService(const DeviceState &state, ServiceManager &manager) : state(state), manager(manager) {} @@ -50,12 +71,12 @@ namespace skyline::service { */ virtual ~BaseService() = default; - virtual std::pair, std::string_view> GetServiceFunction(u32 id) { + virtual ServiceFunctionDescriptor GetServiceFunction(u32 id) { throw std::out_of_range("GetServiceFunction not implemented"); } /** - * @return The name of the class + * @return A string with the name of the service class * @note The lifetime of the returned string is tied to that of the class */ const std::string &GetName();