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
相关产品推荐
相关产品推荐

