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

如何解决调用自定义DLL时出现的未解析外部符号错误?

修复DLL调用的"unresolved external symbol"错误

你的问题出在三个核心点:DLL导入导出宏的错误定义、extern "C"误用在C++类上、静态链接与动态加载方式混用,以下是具体修复方案:


1. 修正DLL导入导出宏

DLL项目和调用项目需要区分导出和导入,用条件编译实现:

修改Header.h的宏定义:

#pragma once
#include <string>

// 条件编译:DLL项目中定义DLL_EXPORTS(在项目属性-预处理器中添加)
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

// extern "C"仅包裹C风格函数,不要包裹C++类
class DLL_API Config {
public:
    static std::string path;
    static std::string test;
    static void get_file();
};

extern "C" DLL_API Config* GetConfigInstance();

注意:在DLL项目的属性 -> C/C++ -> 预处理器 -> 预处理器定义中添加DLL_EXPORTS,确保编译DLL时用dllexport,调用项目不用加,自动用dllimport。


2. 移除类上的extern "C"

C语言不支持类,extern "C"对C类无效,反而会破坏C的名称修饰,导致链接器找不到类成员的符号。把类从extern "C"块中移出,只保留C风格的导出函数(比如GetConfigInstance)在extern "C"中,避免名称修饰问题。


3. 统一链接方式:二选一

你现在同时用了动态加载(LoadLibrary)和静态链接(依赖.lib),必须统一方式:

方案A:静态链接DLL(推荐,简单直接)

调用项目不需要LoadLibrary,直接通过头文件和.lib链接:

修改main.cpp:

#include <iostream>
#include "Header.h"

int main() {
    Config* config = GetConfigInstance();
    config->get_file();
    std::cout << "img_path: " << Config::path << std::endl;
    std::cout << "test: " << Config::test << std::endl;
    delete config; // 记得释放内存,避免泄漏

    return 0;
}

确保调用项目已配置:

  • 包含路径:添加DLL项目的头文件目录
  • 库路径:添加DLL项目生成的.lib文件目录
  • 链接输入:添加对应的.lib文件名(比如Util_aoi_model.lib)

方案B:纯动态加载(无需.lib)

如果必须动态加载,需要为类的所有成员函数和静态变量获取函数指针,不能直接通过头文件调用:

步骤1:DLL项目中导出所有需要调用的函数

修改Header.h,添加C风格的导出函数来封装类的操作:

#pragma once
#include <string>

#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

extern "C" {
    DLL_API void* GetConfigInstance();
    DLL_API void Config_GetFile(void* config);
    DLL_API const char* Config_GetPath();
    DLL_API const char* Config_GetTest();
    DLL_API void DestroyConfig(void* config);
}

步骤2:DLL项目中实现这些封装函数

修改dllmain.cpp,添加:

// 之前的Config类实现保持不变

void* GetConfigInstance() {
    return new Config();
}

void Config_GetFile(void* config) {
    static_cast<Config*>(config)->get_file();
}

const char* Config_GetPath() {
    return Config::path.c_str();
}

const char* Config_GetTest() {
    return Config::test.c_str();
}

void DestroyConfig(void* config) {
    delete static_cast<Config*>(config);
}

步骤3:调用项目中动态加载所有函数

修改main.cpp:

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

// 定义函数指针类型
typedef void* (*GetConfigInstanceFunc)();
typedef void (*Config_GetFileFunc)(void*);
typedef const char* (*Config_GetPathFunc)();
typedef const char* (*Config_GetTestFunc)();
typedef void (*DestroyConfigFunc)(void*);

int main() {
    HINSTANCE hinstLib = LoadLibrary(TEXT("Util_aoi_model.dll"));
    if (!hinstLib) {
        std::cerr << "Failed to load DLL" << std::endl;
        return 1;
    }

    // 获取所有函数地址
    GetConfigInstanceFunc getInstance = (GetConfigInstanceFunc)GetProcAddress(hinstLib, "GetConfigInstance");
    Config_GetFileFunc getFile = (Config_GetFileFunc)GetProcAddress(hinstLib, "Config_GetFile");
    Config_GetPathFunc getPath = (Config_GetPathFunc)GetProcAddress(hinstLib, "Config_GetPath");
    Config_GetTestFunc getTest = (Config_GetTestFunc)GetProcAddress(hinstLib, "Config_GetTest");
    DestroyConfigFunc destroyConfig = (DestroyConfigFunc)GetProcAddress(hinstLib, "DestroyConfig");

    if (!getInstance || !getFile || !getPath || !getTest || !destroyConfig) {
        std::cerr << "Failed to get function addresses" << std::endl;
        FreeLibrary(hinstLib);
        return 1;
    }

    // 使用DLL功能
    void* config = getInstance();
    getFile(config);
    std::cout << "img_path: " << getPath() << std::endl;
    std::cout << "test: " << getTest() << std::endl;
    destroyConfig(config);

    FreeLibrary(hinstLib);
    return 0;
}

4. 额外注意事项

  • 确保DLL和调用项目的编译架构一致(都是x86或都是x64),否则会出现链接或加载错误。
  • 运行调用项目时,需要把DLL文件放在可执行文件目录下,或者系统路径中。
  • 静态成员变量Config::path和Config::test是全局的,多个实例会共享,注意线程安全问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:17:53