Revamp: Transition HarmonyLink to C++ with DLL support
This transformative commit marks the evolution of HarmonyLink from a Rust-based server-side application to a C++ implemented, C-compatible dynamic link library (DLL). We've restructured the codebase to streamline integration into games, eliminating the need for a server setup by end-users. Key Changes: - Introduced .gitattributes and .gitmodules to manage new dependencies and collaborations. - Replaced the GitHub workflow files with CMake configurations to support the new C++ build system. - Introduced a comprehensive set of header and implementation files defining the core functionality, platform-specific utilities, and cross-platform compatibility layers. - Removed all Rust-specific files (Cargo.toml, Cargo.lock, etc.) and references to ensure a clean transition to the C++ environment. - Implemented new testing mechanisms within HarmonyLinkTest to ensure robustness and reliability of the DLL. - Excised previous server-side components and models to focus on the DLL's direct integration into consumer applications. This update is a direct response to community feedback, showcasing our commitment to adaptability and innovation. HarmonyLink 2.0 is now more accessible, efficient, and tailored for diverse gaming environments, providing developers with an unparalleled level of hardware-software harmony. Please refer to the updated README for more details on the new structure and how to integrate HarmonyLink 2.0 into your projects.
This commit is contained in:
parent
d13fc728df
commit
6bf68eb298
60 changed files with 1629 additions and 2389 deletions
14
HarmonyLinkLib/include/Core.h
Normal file
14
HarmonyLinkLib/include/Core.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright (C) 2023 Jordon Brooks
|
||||
|
||||
#pragma once
|
||||
|
||||
// Use a preprocessor definition to switch between export and import declarations
|
||||
#ifdef _WIN32
|
||||
#ifdef HARMONYLINKLIB_EXPORTS
|
||||
#define HARMONYLINKLIB_API __declspec(dllexport)
|
||||
#else
|
||||
#define HARMONYLINKLIB_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define HARMONYLINKLIB_API
|
||||
#endif
|
19
HarmonyLinkLib/include/Enums/EDevice.h
Normal file
19
HarmonyLinkLib/include/Enums/EDevice.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Enum class for representing different types of devices
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
enum class EDevice : uint8_t
|
||||
{
|
||||
DESKTOP,
|
||||
LAPTOP,
|
||||
HANDHELD,
|
||||
|
||||
STEAM_DECK,
|
||||
// ROG_ALLY
|
||||
// AYONEO_SLIDE
|
||||
// etc...
|
||||
};
|
||||
}
|
15
HarmonyLinkLib/include/Enums/EPlatform.h
Normal file
15
HarmonyLinkLib/include/Enums/EPlatform.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Enum class for representing different operating platforms
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
enum class EPlatform : uint8_t
|
||||
{
|
||||
WINDOWS,
|
||||
LINUX,
|
||||
MAC,
|
||||
UNIX,
|
||||
};
|
||||
}
|
165
HarmonyLinkLib/include/FString.h
Normal file
165
HarmonyLinkLib/include/FString.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "Core.h" // Replace with actual API export macro
|
||||
|
||||
/**
|
||||
* @file FString.h
|
||||
* @brief FString Class - Custom String Management for DLL Export
|
||||
*
|
||||
* The FString class is a custom string management class designed to safely encapsulate
|
||||
* string handling and memory management, especially for use in DLLs (Dynamic Link Libraries).
|
||||
* It resolves the common issue of exporting classes containing standard library types,
|
||||
* such as std::string, across DLL boundaries, which can lead to compiler warnings or errors.
|
||||
*
|
||||
* Features:
|
||||
* - Implements basic string operations such as construction, destruction, copy, and move semantics.
|
||||
* - Utilizes smart pointers (std::unique_ptr) for automatic memory management, reducing the risk of memory leaks.
|
||||
* - Provides a simple interface for interacting with character strings, similar to std::string.
|
||||
* - Includes both deep copy semantics for safety and move semantics for performance in object transfers.
|
||||
*
|
||||
* Usage:
|
||||
* FString can be used as a safer alternative to std::string for classes that are exported from a DLL.
|
||||
* It handles memory allocation/deallocation automatically and provides a basic set of string operations.
|
||||
*
|
||||
* Example:
|
||||
* FString myString("Hello, world!");
|
||||
* std::cout << myString.c_str() << std::endl; // Output: Hello, world!
|
||||
*
|
||||
* Note:
|
||||
* - The class is currently designed with basic functionality. Additional features such as
|
||||
* string concatenation, substring, and comparison operations can be added as needed.
|
||||
* - Ensure that the HarmonyLinkLibApi.h (or equivalent) file correctly defines the export macro
|
||||
* for DLL usage.
|
||||
*
|
||||
*/
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
class HARMONYLINKLIB_API FString {
|
||||
public:
|
||||
FString() : data_(new char[1]) {
|
||||
data_[0] = '\0';
|
||||
}
|
||||
|
||||
FString(const char* str) {
|
||||
const size_t len = strlen(str);
|
||||
data_ = new char[len + 1];
|
||||
memcpy(data_, str, len + 1);
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
FString(const FString& other) {
|
||||
const size_t len = strlen(other.data_);
|
||||
data_ = new char[len + 1];
|
||||
memcpy(data_, other.data_, len + 1);
|
||||
}
|
||||
|
||||
~FString() {
|
||||
delete[] data_;
|
||||
}
|
||||
|
||||
// Copy assignment operator
|
||||
FString& operator=(const FString& other) {
|
||||
if (this != &other) {
|
||||
delete[] data_;
|
||||
const size_t len = strlen(other.data_);
|
||||
data_ = new char[len + 1];
|
||||
memcpy(data_, other.data_, len + 1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Concatenation operator for FString objects
|
||||
FString operator+(const FString& other) const {
|
||||
size_t thisLen = strlen(this->data_);
|
||||
size_t otherLen = strlen(other.data_);
|
||||
char* concatenated = new char[thisLen + otherLen + 1];
|
||||
|
||||
memcpy(concatenated, this->data_, thisLen);
|
||||
memcpy(concatenated + thisLen, other.data_, otherLen + 1);
|
||||
|
||||
FString result(concatenated);
|
||||
delete[] concatenated;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Concatenation operator for const char*
|
||||
FString operator+(const char* other) const {
|
||||
return *this + FString(other);
|
||||
}
|
||||
|
||||
// Friend function to allow concatenation with const char* on the left-hand side
|
||||
friend FString operator+(const char* lhs, const FString& rhs) {
|
||||
return FString(lhs) + rhs;
|
||||
}
|
||||
|
||||
// Move constructor
|
||||
FString(FString&& other) noexcept : data_(other.data_) {
|
||||
other.data_ = nullptr;
|
||||
}
|
||||
|
||||
FString(const std::string& str) {
|
||||
const size_t len = str.length();
|
||||
data_ = new char[len + 1];
|
||||
memcpy(data_, str.c_str(), len + 1);
|
||||
}
|
||||
|
||||
// Move assignment operator
|
||||
FString& operator=(FString&& other) noexcept {
|
||||
if (this != &other) {
|
||||
delete[] data_;
|
||||
data_ = other.data_;
|
||||
other.data_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const FString& other) const {
|
||||
return strcmp(data_, other.data_) == 0;
|
||||
}
|
||||
|
||||
// Method to get a lowercase version of the string
|
||||
static FString to_lower(FString& from)
|
||||
{
|
||||
for (size_t i = 0; i < strlen(from.data_); ++i) {
|
||||
from.data_[i] = static_cast<char>(std::tolower(static_cast<unsigned char>(from.data_[i])));
|
||||
}
|
||||
return from;
|
||||
}
|
||||
|
||||
// Overloaded static method to handle const char*
|
||||
static FString to_lower(const char* from) {
|
||||
FString temp_string(from); // Create an FString from const char*
|
||||
return to_lower(temp_string); // Reuse the existing to_lower method
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
return data_;
|
||||
}
|
||||
|
||||
private:
|
||||
char* data_ = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<HarmonyLinkLib::FString> {
|
||||
size_t operator()(const HarmonyLinkLib::FString& s) const {
|
||||
size_t hashValue = 5381; // Starting value recommended by the djb2 algorithm
|
||||
const char* str = s.c_str();
|
||||
|
||||
for (size_t i = 0; str[i] != '\0'; ++i) {
|
||||
hashValue = ((hashValue << 5) + hashValue) + static_cast<unsigned char>(str[i]);
|
||||
// Equivalent to hashValue * 33 + str[i]
|
||||
}
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
};
|
||||
}
|
44
HarmonyLinkLib/include/HarmonyLinkLib.h
Normal file
44
HarmonyLinkLib/include/HarmonyLinkLib.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright (C) 2023 Jordon Brooks
|
||||
|
||||
|
||||
/**
|
||||
* IMPORTANT REMINDER:
|
||||
* Do NOT use standard output functions like std::cout and printf anywhere in this codebase.
|
||||
*
|
||||
* Reason:
|
||||
* Unreal Engine 5's packaging tool encounters issues with these functions, leading to
|
||||
* packaging failures. The engine sets stdout to UTF-8, which can cause conflicts with
|
||||
* these standard functions, resulting in a "SECURE CRT: Invalid parameter detected" error
|
||||
* during packaging.
|
||||
*
|
||||
* This issue once required an extensive debugging effort that lasted over 8 hours.
|
||||
* To prevent similar issues in the future and ensure smooth packaging, always use
|
||||
* wide-character versions of these functions, such as wprintf and std::wcout, when working
|
||||
* within the DLL. These functions are compatible with the UTF-8 setting in Unreal Engine 5.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Core.h"
|
||||
#include "Structs/FBattery.h"
|
||||
#include "Structs/FCPUInfo.h"
|
||||
#include "Structs/FDevice.h"
|
||||
#include "Structs/FOSVerInfo.h"
|
||||
|
||||
|
||||
class IPlatformUtilities;
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
extern "C" HARMONYLINKLIB_API bool get_is_wine();
|
||||
|
||||
extern "C" HARMONYLINKLIB_API FCPUInfo* get_cpu_info();
|
||||
|
||||
extern "C" HARMONYLINKLIB_API FDevice* get_device_info();
|
||||
|
||||
extern "C" HARMONYLINKLIB_API FOSVerInfo* get_os_version();
|
||||
|
||||
extern "C" HARMONYLINKLIB_API FBattery* get_battery_status();
|
||||
}
|
13
HarmonyLinkLib/include/HarmonyLinkStruct.h
Normal file
13
HarmonyLinkLib/include/HarmonyLinkStruct.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
struct HarmonyLinkStruct
|
||||
{
|
||||
// Virtual destructor is important for proper cleanup of derived types
|
||||
virtual ~HarmonyLinkStruct() = default;
|
||||
|
||||
// Method to deallocate the object
|
||||
void free() const
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
};
|
22
HarmonyLinkLib/include/Structs/FBattery.h
Normal file
22
HarmonyLinkLib/include/Structs/FBattery.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "HarmonyLinkStruct.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
struct FBattery : HarmonyLinkStruct
|
||||
{
|
||||
bool has_battery;
|
||||
bool is_connected_to_ac;
|
||||
uint8_t battery_percent;
|
||||
|
||||
void to_string() const {
|
||||
std::wcout << "Battery present: " << (has_battery ? "'Yes'" : "'No'") << '\n';
|
||||
std::wcout << "Connected to AC: " << (is_connected_to_ac ? "'Yes'" : "'No'") << '\n';
|
||||
std::wcout << "Battery percent: '" << static_cast<int>(battery_percent) << "%'" << '\n';
|
||||
}
|
||||
};
|
||||
}
|
40
HarmonyLinkLib/include/Structs/FCPUInfo.h
Normal file
40
HarmonyLinkLib/include/Structs/FCPUInfo.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_set>
|
||||
#include "FString.h"
|
||||
|
||||
#include "HarmonyLinkStruct.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
struct FCPUInfo : HarmonyLinkStruct
|
||||
{
|
||||
FString VendorID;
|
||||
FString Model_Name;
|
||||
uint32_t Physical_Cores = 0;
|
||||
uint32_t Logical_Cores = 0;
|
||||
std::unordered_set<FString> Flags;
|
||||
|
||||
void print() const
|
||||
{
|
||||
wprintf(L"VendorID: '%hs'\n", VendorID.c_str());
|
||||
wprintf(L"Model_Name: '%hs'\n", Model_Name.c_str());
|
||||
wprintf(L"Physical_Cores: '%d'\n", Physical_Cores);
|
||||
wprintf(L"Logical_Cores: '%d'\n", Logical_Cores);
|
||||
|
||||
// Initialize a string to hold all flags
|
||||
std::string allFlags;
|
||||
for (const auto& flag : Flags) {
|
||||
allFlags += std::string(flag.c_str()) + " "; // Append each flag followed by a space
|
||||
}
|
||||
|
||||
// Remove the trailing space
|
||||
if (!allFlags.empty()) {
|
||||
allFlags.pop_back();
|
||||
}
|
||||
|
||||
wprintf(L"Flags: '%hs'\n", allFlags.c_str());
|
||||
}
|
||||
};
|
||||
}
|
16
HarmonyLinkLib/include/Structs/FDevice.h
Normal file
16
HarmonyLinkLib/include/Structs/FDevice.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <HarmonyLinkStruct.h>
|
||||
|
||||
#include "Enums/EDevice.h"
|
||||
#include "Enums/EPlatform.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
// Struct to represent a specific device with both platform and device type
|
||||
struct FDevice : HarmonyLinkStruct
|
||||
{
|
||||
EPlatform platform;
|
||||
EDevice device;
|
||||
};
|
||||
}
|
50
HarmonyLinkLib/include/Structs/FOSVerInfo.h
Normal file
50
HarmonyLinkLib/include/Structs/FOSVerInfo.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "FString.h"
|
||||
#include "HarmonyLinkStruct.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
struct FOSVerInfo : HarmonyLinkStruct {
|
||||
// 'name' represents the operating system's name, e.g., "Ubuntu" in Linux or "Windows" in Windows systems.
|
||||
FString name;
|
||||
|
||||
// 'version' is a numerical representation of the OS version. In Linux, it might be the kernel version,
|
||||
// whereas in Windows, it could be the major version number like 10 for Windows 10.
|
||||
uint32_t version = 0;
|
||||
|
||||
// 'id' is a unique identifier for the OS. In Linux, it might be a lower-case string like "ubuntu".
|
||||
// In Windows, this could map to the edition ID, such as "Professional".
|
||||
FString id;
|
||||
|
||||
// 'version_id' is a string representing the specific version of the OS.
|
||||
// For example, "20.04" in Ubuntu or "1909" in Windows 10.
|
||||
FString version_id;
|
||||
|
||||
// 'version_codename' is a codename for the OS version, if available.
|
||||
// This is common in Linux distributions (e.g., "focal" for Ubuntu 20.04) but not typically used in Windows.
|
||||
FString version_codename;
|
||||
|
||||
// 'pretty_name' is a more readable version of the name, potentially including the version and codename.
|
||||
// For example, "Ubuntu 20.04 LTS (Focal Fossa)" or "Windows 10 Pro".
|
||||
FString pretty_name;
|
||||
|
||||
// 'variant_id' is an identifier for the specific variant of the OS, if available.
|
||||
// For example, in Linux distributions, this might be "desktop" for the desktop edition,
|
||||
// "server" for the server edition, or "core" for a minimal installation. It helps distinguish
|
||||
// between different flavors or editions of the same version.
|
||||
// On the Steam Deck, this is set to "steamdeck".
|
||||
FString variant_id;
|
||||
|
||||
void print() const
|
||||
{
|
||||
wprintf(L"Name: '%hs'\n", name.c_str());
|
||||
wprintf(L"Version: '%d'\n", version);
|
||||
wprintf(L"ID: '%hs'\n", id.c_str());
|
||||
wprintf(L"Version ID: '%hs'\n", version_id.c_str());
|
||||
wprintf(L"Version Codename: '%hs'\n", version_codename.c_str());
|
||||
wprintf(L"Pretty Name: '%hs'\n", pretty_name.c_str());
|
||||
wprintf(L"Variant ID: '%hs'\n", variant_id.c_str());
|
||||
}
|
||||
};
|
||||
}
|
45
HarmonyLinkLib/include/Version.h
Normal file
45
HarmonyLinkLib/include/Version.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
#pragma once
|
||||
|
||||
#include "Core.h"
|
||||
#include <Version.generated.h>
|
||||
|
||||
#include "FString.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
class HARMONYLINKLIB_API version
|
||||
{
|
||||
public:
|
||||
version() = default;
|
||||
|
||||
static FString ToString()
|
||||
{
|
||||
return HARMONYLINK_VERSION;
|
||||
}
|
||||
|
||||
static FString get_build_timestamp()
|
||||
{
|
||||
return {__TIMESTAMP__};
|
||||
}
|
||||
|
||||
static FString get_git_branch()
|
||||
{
|
||||
return {GIT_BRANCH_NAME};
|
||||
}
|
||||
|
||||
static FString get_git_commit_timestamp()
|
||||
{
|
||||
return {GIT_COMMIT_TIMESTAMP};
|
||||
}
|
||||
|
||||
static bool is_debug()
|
||||
{
|
||||
#ifdef DEBUG_MODE
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
11
HarmonyLinkLib/include/Version.h.in
Normal file
11
HarmonyLinkLib/include/Version.h.in
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Version.h.in
|
||||
#pragma once
|
||||
|
||||
#define HARMONYLINK_VERSION_MAJOR @HarmonyLinkLib_VERSION_MAJOR@
|
||||
#define HARMONYLINK_VERSION_MINOR @HarmonyLinkLib_VERSION_MINOR@
|
||||
#define HARMONYLINK_VERSION_PATCH @HarmonyLinkLib_VERSION_PATCH@
|
||||
#define HARMONYLINK_VERSION_TWEAK @HarmonyLinkLib_VERSION_TWEAK@
|
||||
#define HARMONYLINK_VERSION "@HarmonyLinkLib_VERSION@"
|
||||
|
||||
#define GIT_BRANCH_NAME "@GIT_BRANCH_NAME@"
|
||||
#define GIT_COMMIT_TIMESTAMP "@GIT_COMMIT_TIMESTAMP@"
|
Loading…
Add table
Add a link
Reference in a new issue