You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用GetProcAddress获取的DLL函数后代码无法执行,如何异步处理?

问题描述
  • 已创建包含导出函数GameStart的game.dll,该函数内部包含无限游戏循环及其他逻辑
  • 在Windows控制台程序中通过GetProcAddress获取并调用GameStart后,调用语句之后的代码完全无法执行
  • 关闭游戏窗口时,控制台程序会随之终止,尝试解锁控制台未找到可行方法
  • 需求:实现异步调用或其他解决方案,让控制台程序能正常执行后续代码,且游戏窗口关闭不影响控制台程序

原代码示例

#include <stdio.h> 
#include <windows.h> 
 
typedef int (*MYPROC)(LPTSTR); 
 
VOID main(VOID) 
{ 
    HINSTANCE hinstLib; 
    MYPROC ProcAdd; 
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
 
    hinstLib = LoadLibrary(TEXT("Game")); 
 
    if (hinstLib != NULL) 
    { 
        ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("GameStart")); 
 
        if (NULL != ProcAdd) 
        {
            fRunTimeLinkSuccess = TRUE;
            ProcAdd(); 
        }
 
        // 这段代码永远无法执行,因为GameStart内部是无限循环
        fFreeResult = FreeLibrary(hinstLib); 
    }
 
    if (! fRunTimeLinkSuccess) 
        printf("Message via alternative method\n"); 
}
解决方案

1. 使用CreateThread异步调用GameStart

把GameStart放到单独线程中执行,主线程即可正常运行后续代码。注意调整函数指针类型以匹配线程入口要求:

#include <stdio.h> 
#include <windows.h> 
 
// 匹配线程入口函数的签名要求
typedef DWORD(*GAME_START_PROC)(LPVOID); 
 
VOID main(VOID) 
{ 
    HINSTANCE hinstLib; 
    GAME_START_PROC GameStart; 
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
    HANDLE hGameThread = NULL;
 
    hinstLib = LoadLibrary(TEXT("Game")); 
 
    if (hinstLib != NULL) 
    { 
        GameStart = (GAME_START_PROC) GetProcAddress(hinstLib, TEXT("GameStart")); 
 
        if (NULL != GameStart) 
        {
            fRunTimeLinkSuccess = TRUE;
            // 创建独立线程执行GameStart
            hGameThread = CreateThread(
                NULL,           
                0,              
                (LPTHREAD_START_ROUTINE)GameStart, 
                NULL,           
                0,              
                NULL            
            );
        }
 
        // 现在这段代码可以正常执行
        printf("Game thread started, main thread continues...\n");
        fFreeResult = FreeLibrary(hinstLib); 
    }
 
    if (! fRunTimeLinkSuccess) 
        printf("Message via alternative method\n"); 
 
    // 可选:等待游戏线程结束(注释则主线程直接继续)
    // WaitForSingleObject(hGameThread, INFINITE);
    // CloseHandle(hGameThread);
 
    // 保持控制台窗口打开
    printf("Press any key to exit...\n");
    getchar();
}

注意事项

  • 若GameStart的签名与线程入口(返回DWORD、参数为LPVOID)不匹配,需修改dll中的函数定义,或在控制台端做适配包装
  • 若主线程与游戏线程有共享数据,需用CreateMutex等同步机制保证线程安全

2. 修改GameStart函数,添加退出控制

如果有权限修改game.dll,可以给GameStart加退出逻辑,让函数能主动返回,主线程即可继续执行:

// game.dll中的修改
volatile BOOL g_bGameExit = FALSE;

// 导出函数,调整签名匹配线程要求
DWORD GameStart(LPVOID param)
{
    while (!g_bGameExit)
    {
        // 处理窗口消息,捕获关闭事件
        MSG msg;
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_CLOSE)
            {
                g_bGameExit = TRUE;
                DestroyWindow(msg.hwnd);
                // 不调用PostQuitMessage,避免终止整个进程
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        // 其他游戏循环逻辑
    }
    return 0;
}

// 额外导出函数,用于外部触发退出
__declspec(dllexport) void StopGame()
{
    g_bGameExit = TRUE;
}

控制台端可通过调用StopGame主动终止游戏循环,同时避免游戏窗口关闭时连带终止控制台进程。

3. 分离游戏与控制台为独立进程

如果希望游戏窗口关闭完全不影响控制台,可将game.dll封装成独立EXE,控制台通过CreateProcess启动游戏进程:

#include <stdio.h>
#include <windows.h>

VOID main(VOID)
{
    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
    si.cb = sizeof(si);

    // 启动独立的游戏EXE
    if (CreateProcess(TEXT("Game.exe"), NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
    {
        printf("Game process started successfully\n");
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
    else
    {
        printf("Failed to start game, error: %d\n", GetLastError());
    }

    printf("Main thread continues running...\n");
    printf("Press any key to exit...\n");
    getchar();
}
关键注意点
  • 游戏窗口默认与控制台进程关联,关闭时会发送WM_QUIT终止整个进程,可通过在窗口过程中拦截WM_CLOSE、不调用PostQuitMessage解决
  • 跨线程/进程的资源访问必须保证线程安全

内容的提问来源于stack exchange,提问作者Леонид Русаков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 09:18:36