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

使用OpenCV+CMake开发检测应用时,DLL中类出现未解析外部符号错误

问题:DLL中类的构造函数/方法触发未解析外部符号错误

使用OpenCV和CMake开发检测应用,定义了抽象类Detector及其派生类FaceDetector。项目包含一个可执行文件和两个DLL,但在main.cpp中调用DLL内类的构造函数或方法时,出现未解析外部符号链接错误:

unresolved external symbol "public: __cdecl FaceDetector::FaceDetector(struct detectorProperties)" (??0FaceDetector@@QEAA@UdetectorProperties@@@Z) referenced in function main

目前能正常创建detectorProperties结构体实例、调用drawLabel函数,但类无法正常使用——哪怕是如下的简单Test类,也无法在main中初始化:

class Test {
public:
  Test() {}
}

相关代码与配置

ObjectDetection.h

#pragma once
#include <opencv2/opencv.hpp>

#ifdef OBJECTDETECTION_EXPORTS
#define OBJECTDETECTION_API __declspec(dllexport)
#else
#define OBJECTDETECTION_API __declspec(dllimport)
#endif

extern OBJECTDETECTION_API void drawLabel(cv::Mat & image, std::string label, int left, int top);

extern OBJECTDETECTION_API struct detectorProperties {
    // some variables
};

extern OBJECTDETECTION_API class Detector {
protected:
    std::string modelPath;
    bool shouldSwapRB = false;
    bool active = false;
    bool shouldDrawRect = true;

public:
    virtual void detect(cv::Mat& image) = 0;
};

extern OBJECTDETECTION_API class FaceDetector : public Detector {
private:
    cv::CascadeClassifier cs;
    std::vector<cv::Rect> facesInFrame;
public:
    FaceDetector(detectorProperties props);
    void detect(cv::Mat& image);

};

ObjectDetection.cpp

#include "ObjectDetection.h"

#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
using namespace std;

void drawLabel(cv::Mat & image, string label, int left, int top) {
    // function code
}

FaceDetector::FaceDetector(detectorProperties props) {
    // constructor code
}

// code

main.cpp

#include "ObjectDetection.h"

int main() {
    detectorProperties props;
    props.modelPath = "some/path";

    FaceDetector det = FaceDetector(props);
}

CMake构建输出

Selecting Windows SDK version 10.0.22000.0 to target Windows 10.0.22623.
The C compiler identification is MSVC 19.35.32216.1
The CXX compiler identification is MSVC 19.35.32216.1
Detecting C compiler ABI info
Detecting C compiler ABI info - done
Check for working C compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.35.32215/bin/Hostx64/x64/cl.exe - skipped
Detecting C compile features
Detecting C compile features - done
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.35.32215/bin/Hostx64/x64/cl.exe - skipped
Detecting CXX compile features
Detecting CXX compile features - done
OpenCV ARCH: x64
OpenCV RUNTIME: vc16
OpenCV STATIC: OFF
Found OpenCV 4.7.0 in C:/OpenCV/build/x64/vc16/lib
You might need to add C:\OpenCV\build\x64\vc16\bin to your PATH to be able to run your applications.
Could NOT find WrapVulkanHeaders (missing: Vulkan_INCLUDE_DIR) 
Configuring done (4.5s)
Generating done (0.2s)

顶层CMake文件

# Qt 6.2.4 uses CMake 3.16, so that should be our minimum CMake version
cmake_minimum_required(VERSION 3.16)

# Set the name for the project
project(DetectionApp)

# Specify where should the executables and libraries created
# This helps us avoid copying the files manually or using a post-build command
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMALE_PREFIX_PATH $ENV{Qt6_DIR})

set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_AUTOUIC_SEARCH_PATHS} src/Application)

find_package(OpenCV REQUIRED)
find_package(Qt6 REQUIRED COMPONENTS Gui Core Widgets)

# Add the subdirectories for the different parts of the application
add_subdirectory(src/Application)
add_subdirectory(src/CameraInteraction)
add_subdirectory(src/ObjectDetection)

add_subdirectory(src/CameraInteraction_v2)
add_subdirectory(src/ObjectDetection_v2)
add_subdirectory(src/WebCam)

set(CMAKE_VERBOSE_MAKEFILE ON)

Application CMake文件

# Set the project name
project(Application)

# Add the executable
file(GLOB SOURCE_FILES "*.cpp")
file(GLOB UI_FILES "*.ui")
file(GLOB HEADER_FILES "*.h")
add_executable(${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES} ${UI_FILES})

# Add the libraries
add_dependencies(${PROJECT_NAME}
    CameraInteraction
    ObjectDetection
)

# Allow the headers to be included in main.cpp
target_include_directories(${PROJECT_NAME} PUBLIC
                          "${CMAKE_SOURCE_DIR}/src/CameraInteraction"
                          "${CMAKE_SOURCE_DIR}/src/ObjectDetection"
                           ${OpenCV_INCLUDE_DIRS}
                          )
                    
#Link this project with te runtime output dir
target_link_directories(${PROJECT_NAME} PUBLIC
    ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)

target_link_libraries(${PROJECT_NAME} 
    CameraInteraction
    ObjectDetection
    Qt6::Core
    Qt6::Widgets
    ${OpenCV_LIBS}
)

set_target_properties(${PROJECT_NAME} PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

ObjectDetection库CMake文件

# Set the project name
project(ObjectDetection)

# Take every header and source in the directory
file(GLOB HEADER_FILES "*.h")
file(GLOB SOURCE_FILES "*.cpp")

# Add the library
add_library(${PROJECT_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES})

# Link against OpenCV
target_include_directories(${PROJECT_NAME} PUBLIC ${OpenCV_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PUBLIC ${OpenCV_LIBS})

解决方案

核心问题:类的导出方式错误

Windows下,extern仅适用于全局函数和变量,不能用来导出类。__declspec(dllexport)需要直接修饰类定义,而非搭配extern使用,这是导致链接错误的根本原因。

修复步骤:

  1. 修正头文件中的类/结构体导出写法
    移除类和结构体前的extern,直接用OBJECTDETECTION_API修饰,同时补充detectorProperties缺失的modelPath成员(否则main中访问该成员会编译错误):

    // 修正后的结构体定义
    OBJECTDETECTION_API struct detectorProperties {
        std::string modelPath; // 补充缺失成员
        // 其他变量
    };
    
    // 修正后的抽象类定义
    OBJECTDETECTION_API class Detector {
    protected:
        std::string modelPath;
        bool shouldSwapRB = false;
        bool active = false;
        bool shouldDrawRect = true;
    
    public:
        virtual void detect(cv::Mat& image) = 0;
    };
    
    // 修正后的派生类定义
    OBJECTDETECTION_API class FaceDetector : public Detector {
    private:
        cv::CascadeClassifier cs;
        std::vector<cv::Rect> facesInFrame;
    public:
        FaceDetector(detectorProperties props);
        void detect(cv::Mat& image);
    };
    
  2. 补充缺失的类方法实现
    当前ObjectDetection.cpp中缺少FaceDetector::detect的实现,会引发新的链接错误,需补充:

    void FaceDetector::detect(cv::Mat& image) {
        // 实现检测逻辑
    }
    
  3. 优化CMake链接配置(可选)
    移除Application CMake中的target_link_directories——CMake会自动管理通过add_library创建的库的路径,无需手动指定。

验证修复

修改完成后重新构建项目,链接错误应消失,FaceDetector可正常初始化并调用方法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:08:07