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

C++中如何编写继承应用IShape接口的Triangle类DLL插件(显式链接)

实现方案

一、调整主程序IShape接口的可访问性

  • 必须将主程序中的IShape接口声明为可导出/导入的共享接口,这样DLL才能继承它。在主程序的头文件中添加宏控制:
    #ifdef SHAPE_EXPORTS
    #define SHAPE_API __declspec(dllexport)
    #else
    #define SHAPE_API __declspec(dllimport)
    #endif
    
    class SHAPE_API IShape {
    public:
        virtual double GetArea() const = 0;
        virtual double GetPerimeter() const = 0;
        virtual ~IShape() = default;
        // 主程序原有创建已知形状的工厂方法保留
        static IShape* Create(const std::string& shapeData);
    };
    
  • 主程序编译时定义SHAPE_EXPORTS宏,确保接口符号被导出到run.exe中。

二、编写Triangle.dll的核心代码

  • 创建DLL项目,引入主程序的IShape.h头文件(编译时不定义SHAPE_EXPORTS,自动启用__declspec(dllimport)导入接口)。
  • 实现继承IShape的Triangle类,并导出供主程序调用的C风格函数(避免C++名称 mangling):
    #include "IShape.h"
    #include <cmath>
    #include <string>
    #include <sstream>
    
    class Triangle : public IShape {
    private:
        double sideA, sideB, sideC;
    public:
        Triangle(double a, double b, double c) : sideA(a), sideB(b), sideC(c) {}
        double GetArea() const override {
            double semiPerim = (sideA + sideB + sideC) / 2;
            return sqrt(semiPerim * (semiPerim - sideA) * (semiPerim - sideB) * (semiPerim - sideC));
        }
        double GetPerimeter() const override {
            return sideA + sideB + sideC;
        }
    };
    
    // 导出:判断是否为三角形类型
    extern "C" __declspec(dllexport) bool IsTriangle(const std::string& shapeType) {
        return shapeType == "triangle";
    }
    
    // 导出:创建Triangle实例
    extern "C" __declspec(dllexport) IShape* CreateTriangle(const std::string& shapeData) {
        // 解析格式如"triangle:3,4,5"的数据
        size_t colonPos = shapeData.find(':');
        if (colonPos == std::string::npos) return nullptr;
        
        std::string sidesStr = shapeData.substr(colonPos + 1);
        std::stringstream ss(sidesStr);
        std::string segment;
        double sides[3];
        int idx = 0;
        while (std::getline(ss, segment, ',') && idx < 3) {
            sides[idx++] = std::stod(segment);
        }
        if (idx != 3) return nullptr;
        
        return new Triangle(sides[0], sides[1], sides[2]);
    }
    

三、主程序添加显式加载DLL的逻辑(仅少量修改)

  • 在主程序中添加动态加载DLL、调用导出函数的代码,无需修改原有形状处理核心逻辑:
    #include <windows.h>
    #include <vector>
    #include <string>
    
    // 定义DLL导出函数的指针类型
    typedef bool (*IsShapeTypeFunc)(const std::string&);
    typedef IShape* (*CreateShapeFunc)(const std::string&);
    
    int main() {
        // 原有读取文件、处理已知形状的代码保留
        std::vector<std::string> shapeDllPaths = {"Triangle.dll"}; // 可扩展为扫描目录下所有形状DLL
        std::vector<std::pair<IsShapeTypeFunc, CreateShapeFunc>> extShapeHandlers;
    
        // 加载DLL并注册处理函数
        for (const auto& dllPath : shapeDllPaths) {
            HMODULE hDll = LoadLibraryA(dllPath.c_str());
            if (!hDll) continue; // DLL不存在则跳过,对应版本1无Triangle支持的情况
    
            IsShapeTypeFunc isTriangle = (IsShapeTypeFunc)GetProcAddress(hDll, "IsTriangle");
            CreateShapeFunc createTriangle = (CreateShapeFunc)GetProcAddress(hDll, "CreateTriangle");
            if (isTriangle && createTriangle) {
                extShapeHandlers.emplace_back(isTriangle, createTriangle);
            }
        }
    
        // 处理单个形状数据(示例,实际从文件批量读取)
        std::string shapeData = "triangle:3,4,5";
        std::string shapeType = shapeData.substr(0, shapeData.find(':'));
        IShape* shape = nullptr;
    
        // 先尝试主程序内置的形状
        shape = IShape::Create(shapeData);
        if (!shape) {
            // 尝试扩展DLL中的形状
            for (const auto& handler : extShapeHandlers) {
                if (handler.first(shapeType)) {
                    shape = handler.second(shapeData);
                    break;
                }
            }
        }
    
        if (shape) {
            printf("Area: %.2f\n", shape->GetArea());
            printf("Perimeter: %.2f\n", shape->GetPerimeter());
            delete shape;
        } else {
            printf("Unsupported shape: %s\n", shapeType.c_str());
        }
    
        // 程序退出时卸载DLL(可按需处理)
        // ...
        return 0;
    }
    

四、效果验证

  • 版本1:仅运行run.exe,因未找到Triangle.dll,加载逻辑跳过三角形处理,无法识别该形状。
  • 版本2:将Triangle.dll放在run.exe同目录下,主程序成功加载DLL,调用导出函数创建Triangle实例,正常计算并输出面积、周长。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 21:20:25