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

VS中创建C++ DLL后导出函数未在依赖查看器中显示的问题

DLL导出函数在依赖查看器中无法找到的解决思路

问题背景

我是Visual Studio和DLL项目创建的新手,参考微软官方文档创建了C++ DLL,但生成的DLL在依赖查看器里找不到导出函数,附上头文件和源文件代码,求解决思路。


核心解决思路

1. 验证预处理器宏定义

头文件中通过MATHLIBRARY_EXPORTS宏控制__declspec(dllexport)的启用,需确保:

  • 在DLL项目的属性→C/C++→预处理器→预处理器定义中,已添加MATHLIBRARY_EXPORTS(仅DLL项目添加,调用DLL的项目无需添加)。

2. 确认extern "C"修饰的正确性

C++编译器会对函数名进行名称修饰,导致依赖查看器无法识别原始函数名。代码中已使用extern "C"包裹导出函数,但需确保:

  • 所有需要导出的函数声明和实现都正确关联extern "C",避免遗漏或格式错误。

3. 检查函数声明与实现的一致性

导出函数的声明和实现必须完全匹配(包括函数名、返回值、参数类型):

  • 注意到代码中pritnline存在拼写错误(应为println),这类错误会导致函数无法正确导出,需修正名称统一。

4. 尝试使用.def文件强制导出

若__declspec(dllexport)方式失效,可创建.def文件添加到项目中,明确指定导出函数:

LIBRARY GPAInterface
EXPORTS
    gpa_initialize
    gpa_process_frame
    gpa_drop_detections
    gpa_reset
    gpa_close
    pritnline

VS会基于.def文件生成导出表,无需依赖__declspec(dllexport)修饰。

5. 核对编译配置与文件路径

  • 确保依赖查看器打开的是对应编译版本的DLL(Debug版在Debug目录,Release版在Release目录)。
  • 匹配平台架构:64位DLL需使用64位版本的依赖查看器,32位同理。

6. 用dumpbin工具验证导出表

打开VS开发者命令提示符,执行以下命令查看DLL的导出函数列表:

dumpbin /exports 你的DLL文件路径.dll
  • 若输出包含目标函数,说明函数已导出,可能是依赖查看器缓存或识别问题;
  • 若输出无目标函数,说明导出流程存在问题,需回到前面的步骤排查。

附:相关代码

头文件代码

#pragma once

#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif

#include <cstdint>
#include <cstddef>
#include <cstdlib>
#include <vector>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>

using namespace cv;

struct BoundingBox {
    std::array<uint32_t, 2> top_left;
    std::array<uint32_t, 2> bottom_right;

    BoundingBox(std::array<uint32_t, 2> top_left, std::array<uint32_t, 2> bottom_right)
        : top_left(top_left), bottom_right(bottom_right) {}

    std::string to_string() const {
        return "top left: " + std::to_string(top_left[0]) + ", " + std::to_string(top_left[1]) + ", bottom right: " + std::to_string(bottom_right[0]) + ", " + std::to_string(bottom_right[1]);
    }
};
struct ADROutput {
    BoundingBox bounding_box;
    float score;
    int class_id;

    ADROutput(int class_id, float score, std::array<std::array<uint32_t, 2>, 2> bounding_box)
        : bounding_box(BoundingBox(bounding_box[0], bounding_box[1])), score(score), class_id(class_id) {}

    std::string to_string() const {
        return "Class_id: " + std::to_string(class_id) + ", Confidence: " + std::to_string(score) + ", Bounding Box: " + bounding_box.to_string();
    }
};

struct Detection {
    BoundingBox bounding_box;
    float score;
    int class_id;
};

// Define ProcessFrameOutput structure
typedef struct ProcessFrameOutput {
    uint32_t size;
    ADROutput* detections;
} ProcessFrameOutput;

enum class Mode : int {
    Default = 1,
};
struct DetectorConfig {
    std::string model_path;
    std::string device;
    double iou_threshold;
    double score_threshold;

    // Constructor
    DetectorConfig(std::string model_path, std::string device, double iou_thresh, double score_thresh)
        : model_path(model_path), device(device), iou_threshold(iou_thresh), score_threshold(score_thresh) {}

    // Default constructor
    DetectorConfig() : model_path(""), device("CPU"), iou_threshold(0.45), score_threshold(0.7) {}

    // Function to get weights path
    std::string weights_path() {
        return model_path + ".bin";
    }
};
struct ADRConfig {
    DetectorConfig detector_config;
};

class ModeAlgorithm {
public:
    virtual std::vector<ADROutput> process_frame(const cv::Mat& frame) = 0;
    virtual void reset() = 0;
};

class ADR : public ModeAlgorithm {
private:
    DetectorConfig detector;
    ADRConfig config;

public:
    ADR() {}
    
    std::vector<ADROutput> process_frame(const cv::Mat& frame) {
        std::vector<Detection> detections;
        std::vector<ADROutput> outputs;
        return outputs;
    }

    void reset() {
        //debug("Reset called - TBD implement detector reset to intialization state when needed - processing with current config: {}", config.detector_config);
    }
};

struct YoloADR {
    ModeAlgorithm* adr_var;

    YoloADR(Mode mode) {
        switch (mode) {
        case Mode::Default:
            adr_var = new ADR();
            break;
        }
    }

    std::vector<ADROutput> process_frame(const Mat& frame) {
        return adr_var->process_frame(frame);
    }

    void reset() {
        adr_var->reset();
    }
};

extern "C" __declspec(dllexport) YoloADR* gpa_initialize(Mode mode);
extern "C" __declspec(dllexport) bool gpa_process_frame(YoloADR* adr, uint32_t frame_rows, uint32_t frame_cols, uint32_t frame_stride, void* frame_data, ProcessFrameOutput* detections_out);
extern "C" __declspec(dllexport) void gpa_drop_detections(ProcessFrameOutput* detections);
extern "C" __declspec(dllexport) bool gpa_reset(YoloADR* adr);
extern "C" __declspec(dllexport) bool gpa_close(YoloADR* adr);
extern "C" __declspec(dllexport) void pritnline();

源文件代码

#include <windows.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include <memory>
#include <cstring>
#include "pch.h"
#include "gpa_interface.h"

using namespace cv;

YoloADR* gpa_initialize(Mode mode) {
    // logger::setup_logging();
    // debug("Initialize gpa called with mode ", mode);
    return new YoloADR(mode);
}

template<typename T>
void check_for_null_pointer(T* pointer) {
    if (pointer == nullptr) {
        throw std::runtime_error(std::string(typeid(T).name()) + " pointer is null");
    }
}

bool gpa_process_frame(YoloADR* adr, uint32_t frame_rows, uint32_t frame_cols, uint32_t frame_stride, void* frame_data, ProcessFrameOutput* detections_out)
{
    // debug("Process frame called");
    Mat frame(frame_rows, frame_cols, CV_8UC4, frame_data, frame_stride);
    Mat formatted_frame;
    cvtColor(frame, formatted_frame, COLOR_RGBA2BGR, 3);
    std::vector<ADROutput> detection = adr->process_frame(formatted_frame);
    ADROutput* detection_ptr = detection.data();
    uint32_t size = detection.size();
    ProcessFrameOutput output = {
        output.size = size,
        output.detections = detection_ptr
    };
    std::memcpy(detections_out, &output, sizeof(ProcessFrameOutput));
    return true;
}

void gpa_drop_detections(ProcessFrameOutput* detections) {
    if (detections == nullptr) {
        return;
    }
    delete[] detections->detections;
}

bool gpa_reset(YoloADR* adr) {
    adr->reset();
    return true;
}

bool gpa_close(YoloADR* adr)
{
    try {
        //debug("Close called");
        check_for_null_pointer(adr);
        delete adr;
        return true;
    }
    catch (...) {
        return false;
    }
}

void pritnline()
{
    std::cout << "print" << std::endl;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:14:56