diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index d74a69472a..f7cec818c4 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -231,12 +231,12 @@ class DPP_EXPORT cluster { /** * @brief dpp::cluster is non-copyable */ - cluster& operator=(const cluster&) = delete; + cluster& operator=(const cluster&) = delete; /** * @brief dpp::cluster is non-moveable */ - cluster& operator=(const cluster&&) = delete; + cluster& operator=(const cluster&&) = delete; /** * @brief Destroy the cluster object diff --git a/include/dpp/export.h b/include/dpp/export.h index c8ba8f6f69..24d6bfe81a 100644 --- a/include/dpp/export.h +++ b/include/dpp/export.h @@ -59,6 +59,62 @@ #define DPP_EXPORT #endif +namespace dpp { + +/** + * @brief Represents a build configuration. On some platforms (e.g. Windows) release isn't compatible with debug, so we use this enum to detect it. + */ +enum class build_type { + /** + * @brief Universal build, works with both debug and release + */ + universal, + + /** + * @brief Debug build + */ + debug, + + /** + * @brief Release build + */ + release +}; + +template +extern bool DPP_EXPORT validate_configuration(); + +#if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_GAME) || defined(UE_EDITOR) || defined(UE_BUILD_SHIPPING_WITH_EDITOR) || defined(UE_BUILD_DOCS) + /* + * We need to tell DPP to NOT do the version checker if something from Unreal Engine is defined. + * We have to do this because UE is causing some weirdness where the version checker is broken and always errors. + * This is really only for DPP-UE. There is no reason to not do the version checker unless you are in Unreal Engine. + */ + #define DPP_BYPASS_VERSION_CHECKING +#endif /* UE */ + +#ifndef DPP_BUILD /* when including dpp */ + /** + * Version checking, making sure the program is in a configuration compatible with DPP's. + * + * Do NOT make these variables constexpr. + * We want them to initialize at runtime so the function can be pulled from the shared library object. + */ + #ifndef DPP_BYPASS_VERSION_CHECKING + #if defined(_WIN32) + #ifdef _DEBUG + inline const bool is_valid_config = validate_configuration(); + #else + inline const bool is_valid_config = validate_configuration(); + #endif /* _DEBUG */ + #else + inline const bool is_valid_config = validate_configuration(); + #endif /* _WIN32 */ + #endif /* !DPP_BYPASS_VERSION_CHECKING */ +#endif /* !DPP_BUILD */ + +} + #ifndef _WIN32 #define SOCKET int #else diff --git a/include/dpp/restresults.h b/include/dpp/restresults.h index a340b50ebc..f38da6de52 100644 --- a/include/dpp/restresults.h +++ b/include/dpp/restresults.h @@ -48,36 +48,6 @@ namespace dpp { -#ifdef _WIN32 - #ifdef _DEBUG - extern "C" DPP_EXPORT void you_are_using_a_debug_build_of_dpp_on_a_release_project(); - #else - extern "C" DPP_EXPORT void you_are_using_a_release_build_of_dpp_on_a_debug_project(); - #endif -#endif - -struct DPP_EXPORT version_checker { - version_checker() { - #ifdef _WIN32 - #ifdef _DEBUG - you_are_using_a_debug_build_of_dpp_on_a_release_project(); - #else - you_are_using_a_release_build_of_dpp_on_a_debug_project(); - #endif - #endif - } -}; - -/* - * We need to tell DPP to NOT do the version checker if something from Unreal Engine is defined. - * We have to do this because UE is causing some weirdness where the version checker is broken and always errors. - * This is really only for DPP-UE. There is no reason to not do the version checker unless you are in Unreal Engine. - */ -#if !defined(UE_BUILD_DEBUG) && !defined(UE_BUILD_DEVELOPMENT) && !defined(UE_BUILD_TEST) && !defined(UE_BUILD_SHIPPING) && !defined(UE_GAME) && !defined(UE_EDITOR) && !defined(UE_BUILD_SHIPPING_WITH_EDITOR) && !defined(UE_BUILD_DOCS) -static version_checker dpp_vc; -#endif - - /** * @brief A list of shards */ diff --git a/src/dpp/cluster.cpp b/src/dpp/cluster.cpp index 05e5e9ba17..7077ae48c1 100644 --- a/src/dpp/cluster.cpp +++ b/src/dpp/cluster.cpp @@ -35,16 +35,6 @@ namespace dpp { -#ifdef _WIN32 - #ifdef _DEBUG - extern "C" void you_are_using_a_debug_build_of_dpp_on_a_release_project() { - } - #else - extern "C" void you_are_using_a_release_build_of_dpp_on_a_debug_project() { - } - #endif -#endif - /** * @brief An audit reason for each thread. These are per-thread to make the cluster * methods like cluster::get_audit_reason and cluster::set_audit_reason thread safe across @@ -70,6 +60,38 @@ template std::function make_intent_warning(cluster* }; } +template +bool validate_configuration() { +#ifdef _DEBUG + constexpr build_type expected = build_type::debug; +#else + constexpr build_type expected = build_type::release; +#endif +#ifdef _WIN32 + if constexpr (BuildType != build_type::universal && BuildType != expected) { + MessageBox( + nullptr, + "Mismatched Debug/Release configurations between project and dpp.dll.\n" + "Please ensure both your program and the D++ DLL file are both using the same configuration.\n" + "The program will now terminate.", + "D++ Debug/Release mismatch", + MB_OK | MB_ICONERROR + ); + /* Use std::runtime_rror here because dpp exceptions use std::string and that would crash when catching, because of ABI */ + throw std::runtime_error("Mismatched Debug/Release configurations between project and dpp.dll"); + } + return true; +#else + return true; +#endif +} + +template bool DPP_EXPORT validate_configuration(); + +template bool DPP_EXPORT validate_configuration(); + +template bool DPP_EXPORT validate_configuration(); + cluster::cluster(const std::string &_token, uint32_t _intents, uint32_t _shards, uint32_t _cluster_id, uint32_t _maxclusters, bool comp, cache_policy_t policy, uint32_t request_threads, uint32_t request_threads_raw) : default_gateway("gateway.discord.gg"), rest(nullptr), raw_rest(nullptr), compressed(comp), start_time(0), token(_token), last_identify(time(nullptr) - 5), intents(_intents), numshards(_shards), cluster_id(_cluster_id), maxclusters(_maxclusters), rest_ping(0.0), cache_policy(policy), ws_mode(ws_json)