c++ - 如何一次运行 3 个函数?

标签 c++

我有一个名为“everything”的项目,里面有3个源文件,“glow”、“radar”、“trigger”。在里面,每一个都有一个函数(int glow {code},intradar {code},int trigger {code})。我知道我需要一个主函数来成功调试应用程序。但问题是:如果您将所有 3 个函数都设置为“int main” - 您将无法调试(我也知道这一点)。如果我将 .cpp 文件中的一个函数的名称设置为“int main”,则只能调试那个函数,其余的 .cpp 文件根本不起作用,它们会被编译,但不会发生其他任何事情。
所以我想,也许我应该制作另一个名为 main.cpp 的 .cpp 文件。然后我想,也许将其他源文件包含到这个主文件中会起作用。在这个“main.cpp”文件中,如果我这样做

#include "glow.cpp"
#include "radar.cpp"
#include "trigger.cpp"



int main()
{
    glow();
    radar();
    trigger();
} 

然后编译,只有发光功能被渲染。我不明白我应该怎么做,我不希望同时打开 3 个控制台应用程序,以便每个功能都能正常工作。

下面我将列出每个的源代码。

发光.cpp
#include "ProcMem.h"
#include "csgo.hpp"
#include <ctime>
#include <chrono>
#include <iostream>

using namespace std;
using namespace hazedumper;
using namespace netvars;
using namespace signatures;


ProcMem GZUZ;
DWORD clientDll;
DWORD localPly;

const DWORD TO = 0xF4;
const DWORD HP = 0x100;
const DWORD ELD = 0x10;



int glow()
{
    char proc[9] = "csgo.exe";
    char module[20] = "client_panorama.dll";
    GZUZ.Process(proc);
    clientDll = GZUZ.Module(module);
    do
    {
        localPly = GZUZ.Read<DWORD>(clientDll + dwLocalPlayer);
    } while (localPly == NULL);

    DWORD glowObj = GZUZ.Read<DWORD>(clientDll + dwGlowObjectManager);

    while (true)
    {
        localPly = GZUZ.Read<DWORD>(clientDll + dwLocalPlayer);
        int myTeam = GZUZ.Read<int>(localPly + TO);
        for (short int i = 0; i < 64; i++)
        {
            DWORD entity = GZUZ.Read<DWORD>(clientDll + dwEntityList + i * 0x10);
            if (entity != NULL)
            {
                int GIDX = GZUZ.Read<int>(entity + m_iGlowIndex);
                int entityTeam = GZUZ.Read<int>(entity + TO);
                int entityHP = GZUZ.Read<int>(entity + HP);
                if (entityTeam != myTeam)
                {
                    GZUZ.Write<float>(glowObj + ((GIDX * 0x38) + 0x4), 0.5);
                    GZUZ.Write<float>(glowObj + ((GIDX * 0x38) + 0x8), 1.6);
                    GZUZ.Write<float>(glowObj + ((GIDX * 0x38) + 0xC), 1.8);
                    GZUZ.Write<float>(glowObj + ((GIDX * 0x38) + 0x10), 0.5);
                }
                else
                {
                    GZUZ.Write<float>(glowObj + ((GIDX * 0x38) + 0x4), 0);
                    GZUZ.Write<float>(glowObj + ((GIDX * 0x38) + 0x8), 0);
                    GZUZ.Write<float>(glowObj + ((GIDX * 0x38) + 0xC), 0);
                    GZUZ.Write<float>(glowObj + ((GIDX * 0x38) + 0x10), 0);
                }
                GZUZ.Write<bool>(glowObj + ((GIDX * 0x38) + 0x24), true);
                GZUZ.Write<bool>(glowObj + ((GIDX * 0x38) + 0x25), false);
            }
        }
        Sleep(1);
    }

}

雷达.cpp
#include "ProcMem.h"
#include "csgo.hpp"
#include <ctime>
#include <chrono>
#include <iostream>

using namespace std;
using namespace hazedumper;
using namespace netvars;
using namespace signatures;

ProcMem mem;



int radar() {
    char proc[9] = "csgo.exe";
    char module[20] = "client_panorama.dll";
    mem.Process(proc);
    DWORD gameModule = mem.Module(module);

    while (true) {
        for (short int i = 0; i < 64; i++) { //checks for every available entity, 0 is local player
            DWORD entity = mem.Read<DWORD>(gameModule + dwEntityList + i * 0x10); 
            if (entity != NULL)
            {
                mem.Write(entity + m_bSpotted, true);
            }
        }
        Sleep(50);
    }
}

触发器.cpp
#include "ProcMem.h"
#include "csgo.hpp"
#include <ctime>
#include <chrono>
#include <iostream>

using namespace std;
using namespace hazedumper;
using namespace netvars;
using namespace signatures;

void Shoot();


ProcMem LX;
DWORD cDll;
DWORD lPly;

const DWORD teamOffs = 0xF4;
const DWORD health = 0x100;
const DWORD entLoopDist = 0x10;

int trigger()
{
    char proc[9] = "csgo.exe";
    char module[20] = "client_panorama.dll";
    LX.Process(proc);
    cDll = LX.Module(module);
    lPly = LX.Read<DWORD>(cDll + dwLocalPlayer);

    while (true)
    {
        Shoot();
        Sleep(1);
    }
}

void Shoot()
{
    DWORD activeWeapon = LX.Read<DWORD>(lPly + m_hActiveWeapon); 
    DWORD entNum = activeWeapon & 0xFFF;
    DWORD wID = LX.Read<DWORD>(cDll + dwEntityList + (entNum - 1) * entLoopDist); 
    int mywID = LX.Read<int>(wID + m_iItemDefinitionIndex); //checks for the weapon we are using 
    bool isScoped = LX.Read<bool>(lPly + m_bIsScoped); //if we are scoped
    int myTeam = LX.Read<int>(lPly + teamOffs); //checks for our team
    int xhairEnt = LX.Read<int>(lPly + m_iCrosshairId); //checks to see if we're hovering over somebody
    DWORD entity = LX.Read<DWORD>(cDll + dwEntityList + (xhairEnt - 1) * entLoopDist); //checks for the available entities using client dll
    int enemyHP = LX.Read<int>(entity + health); // checks for enemy hp
    int enemyTeam = LX.Read<int>(entity + teamOffs); // checks for enemy team

    if (GetKeyState(VK_MENU) && enemyTeam != myTeam && enemyHP > 0) // &0x8000 checks if alt is still pressed 
    {
        bool weapon = (mywID == 9) || (mywID == 40) || (mywID == 38) || (mywID == 11);

        if ((weapon&&isScoped) || !weapon)
        {
            Sleep(0.35);
            LX.Write<int>(cDll + dwForceAttack, 5);
            Sleep(50);
            LX.Write<int>(cDll + dwForceAttack, 4);
            Sleep(350);     
        }
    }
}

PS::如果你想知道为什么我在一个源文件中使用 GZUZ 读取和写入内存,在另一个源文件中使用 LX,在另一个源文件中使用 Mem,我只是不能全部使用 Mem,这正是我想出的解决方案当时。我将尝试将每一行代码再次放入一个大源文件并编译(这听起来很疯狂,因为我在做同样的事情时期望得到不同的结果)。

最佳答案

当你这样做时:

int main()
{
    glow();
    radar();
    trigger();
} 

这三个函数将依次运行,一个接一个。

问题是您已经将每个函数设计为在无限循环中永远运行,因此辉光永远不会结束,雷达和触发器永远没有机会运行。

您可以采取两种方法。首先是您可以在多个 greads 中运行,这允许您在不修改现有代码的情况下并行运行多个执行线程。这是一种无需太多修改即可重用现有代码的相当简单直接的方法,但是如果您需要您的函数实际相互交互或修改共享数据,您现在必须处理多线程代码、竞争条件,锁定,同步,死锁以及多线程的所有怪癖,如果您不小心,可能很难使用。

另一种方法是,您可以重写您的函数,让它们轮流运行,而不是在无限循环中运行您的函数。

因此,如果您从一个具有如下功能的程序开始:
void funcA() {
    context contextA;
    while (true) {
        doA(&contextA);
    }
}

void funcB() {
    context contextB;
    while (true) {
        doB(&contextB);
    }
}

重写它,以便它们共享一个循环:
int main()
{
    context contextA;
    context contextB;
    while (true) {
        doA(&contextA);
        doB(&contextB);
    }
} 

此循环将在单个线程中运行所有函数,但它们会轮流运行,而不是为自己占用整个线程。请注意,您应该避免在函数内部执行诸如 sleep() 之类的操作,因为这也会阻塞所有其他函数。

相反,您希望重写这些 sleep 以将控制权交还给主函数,并重新安排回调以继续执行,以便稍后在 sleep 应该过期时调用。这种延续回调调度的使用可以使用优先级队列来实现,以制作通常称为事件驱动编程或异步编程的代码架构。

如果您有幸使用最新的编译器,您可以通过使用新的 C++20 协程显着简化异步编程。

关于c++ - 如何一次运行 3 个函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59307573/

相关文章:

c++ - 使用 ifstream.read(buf, length) 读取文件 - 接收损坏的数据(大多数情况下)

c++ - 不能对 const 对象使用 dynamic_cast

c++ - 包装 std::thread 调用函数

c++ - 使用 CMake 编译时更改头文件的位置会导致缺少 vtable 错误

c++ - 如何控制 gettext 系统中的翻译?

C++如何将字符串数组中的点设置为枚举变量

c++ - QList 元素的段错误

c# - 将多维数组从托管代码传递到非托管代码

c++ - 如何调试加载共享库

c++ - 是否应该将 GUI 应用程序警告消息发送到 std::cerr?