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

C++程序调用DLL函数失败问题排查及正确实现方案

问题描述

我正尝试使用C++17编写程序调用共享库DLL中的函数。

待调用的DLL由名为test.cpp的C++文件编译而来,该文件仅包含一个test函数:

#include <iostream>

int test()
{
    std::cout << "test\n";
    
    return 0;
}

通过Visual Studio 2022原生命令提示符执行以下命令编译:

cl.exe /LD test.cpp

生成名为test.dll的DLL文件。

我参考相关技术文档编写了加载DLL函数的程序:

#include <iostream>
#include <string>
#include <windows.h>
#include <locale>
#include <codecvt>

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> StringConverter;
typedef int(__stdcall* DLLFx)();

std::string GetWorkingDir()
{
    TCHAR buffer[MAX_PATH] = { 0 };
    GetModuleFileName(NULL, buffer, MAX_PATH);
    std::wstring::size_type pos = std::wstring(buffer).find_last_of(L"\\/");

    return StringConverter.to_bytes(std::wstring(buffer).substr(0, pos).c_str()) + "\\";
}

bool LoadDLLFunction(std::string libPath, std::string fxName)
{
    HINSTANCE hGetProcIDDLL = LoadLibrary((WCHAR*)StringConverter.from_bytes(libPath.c_str()).data());

    if (!hGetProcIDDLL)
    {
        std::cout << "ERROR: Could not locate DLL file\"" + libPath + "\"!\n";

        return false;
    }

    DLLFx fx = (DLLFx)GetProcAddress(hGetProcIDDLL, (CHAR*)StringConverter.from_bytes(fxName.c_str()).data());

    if (!fx)
    {
        std::cout << "ERROR: Could not locate function \"" + fxName + "\" in DLL file \"" + libPath + "\"!\n";

        return false;
    }

    return true;
}

int main()
{
    std::string workDir = GetWorkingDir();
    bool result = LoadDLLFunction(workDir + "test.dll", "test");

    if (result)
    {
        std::cout << "Result of loaded DLL function call: " << DLLFx() << "\n";
    }

    std::cout << "\n";

    system("pause");

    return 0;
}

程序中的关键部分说明:

  • 全局变量StringConverter用于将常规std::string转换为Windows API所需的std::wstring类型(C++17及以后已废弃)。
  • 全局类型定义DLLFx是指向DLL中加载函数的指针类型。
  • GetWorkingDir函数用于获取程序当前工作目录。
  • LoadDLLFunction函数用于加载DLL中的函数。

我尝试调用加载的函数并显示返回结果(预期返回0,同时控制台打印test字符串),但程序能找到并加载DLL,却无法定位其中的test函数,始终输出错误信息:ERROR: Could not locate function "test" in DLL file "test.dll"!。

我猜测可能是DLL路径或函数名的字符串转换问题,但不确定是否遗漏了底层字符串机制。


尝试修改记录

根据相关建议,我对test.cpp进行了修改,添加extern "C"和__declspec(dllexport)标记,同时添加DllMain函数:

#include <iostream>
#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C"
{
    int __declspec(dllexport) test()
    {
        std::cout << "test\n";
        return 0;
    }
}

重新编译为test.dll后,执行dumpbin /exports test.dll命令,输出显示test已被导出:

Dump of file test.dll

File Type: DLL

  Section contains the following exports for test.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00001180 test

  Summary

        3000 .data
        3000 .pdata
       12000 .rdata
        1000 .reloc
       23000 .text
        1000 _RDATA

但程序仍无法定位test函数。我还尝试简化GetProcAddress的函数名参数为fxName.c_str(),以及修改函数名为test_fx,均未解决问题。

我想知道究竟遗漏了什么?从C++程序加载并调用DLL函数的正确方法是什么?


内容的提问来源于stack exchange,提问作者Runsva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 00:40:56