Live++ integration
Live++ is a generic hot reload solution for C++ applications. D0 requires the following integration to work correctly:1. Copy & paste this code just below your
#include "LPP_API_x64_CPP.h"
include (note: you may need to include Windows.h
if it is not already).
LPP_NAMESPACE_BEGIN
static bool s_agentRunning = true;
static HANDLE s_agentThread = 0;
DWORD WINAPI D0_LivePPAgentThread(LPVOID param)
{
LppSynchronizedAgent* agent = (LppSynchronizedAgent*)param;
const LppReloadOption option = LPP_RELOAD_OPTION_SYNCHRONIZE_WITH_COMPILATION_AND_RELOAD;
const LppReloadBehaviour behaviour = LPP_RELOAD_BEHAVIOUR_WAIT_UNTIL_CHANGES_ARE_APPLIED;
bool firstReload = true;
while (s_agentRunning) {
if (agent->WantsReload(option)) {
agent->Reload(behaviour);
if (firstReload) {
agent->EnableModule(LppGetCurrentModulePath(), LPP_MODULES_OPTION_ALL_IMPORT_MODULES, 0, 0);
while (!agent->WantsReload(option)) {
agent->ScheduleReload();
Sleep(30);
}
agent->Reload(behaviour);
firstReload = false;
}
}
Sleep(10);
}
return 0;
}
bool D0_StartSynchronizedAgentWithPreferences(LppSynchronizedAgent* agent, const LppLocalPreferences* localPrefs, const wchar_t* absoluteOrRelativePathWithoutSlash, const LppProjectPreferences* prefs)
{
LppProjectPreferences fixedPrefs = prefs ? *prefs : LppCreateDefaultProjectPreferences();
fixedPrefs.exceptionHandler.order = 0;
*agent = LppCreateSynchronizedAgentWithPreferences(localPrefs, absoluteOrRelativePathWithoutSlash, &fixedPrefs);
s_agentThread = CreateThread(0, 0, &D0_LivePPAgentThread, agent, 0, 0);
return LppIsValidSynchronizedAgent(agent) && s_agentThread != 0;
}
void D0_DestroySynchronizedAgent(LppSynchronizedAgent* agent)
{
s_agentRunning = false;
WaitForSingleObject(s_agentThread, INFINITE);
LppDestroySynchronizedAgent(agent);
}
LPP_NAMESPACE_END
2. Replace your existing agent initialization code with the call to new code:
lpp::LppSynchronizedAgent agent;
lpp::D0_StartSynchronizedAgentWithPreferences(&agent, NULL, absoluteOrRelativePathWithoutSlash, NULL);
Where
absoluteOrRelativePathWithoutSlash
is the same path you used in your existing code.3. Destroy the agent when the application is closing:
lpp::D0_DestroySynchronizedAgent(&agent);
Why is this required?
There are two issues that are present when starting debugging with Live++ and D0:- Live++ will catch exceptions that need to be handled by D0 first. This is fixed by adding
exceptionHandler.order = 0;
to the agent preferences. -
Live++ allocates pretty much all memory around your code to load new patches close enough to the original code. If this happens before the debugger attaches, D0 will not be able to use any of that space for its own patches.
This is fixed by moving the agent
EnableModule
call to when the first reload is requested. This provides enough time for D0 to initialize and obtain some memory for its relocations.
If you have any issues with D0 or the integration, you can talk to me directly on Discord: