【问题标题】:How to add compatibility with library structure without adding dependency on library?如何在不增加对库的依赖的情况下添加与库结构的兼容性?
【发布时间】:2018-12-20 20:50:12
【问题描述】:

我目前正在编写一个有时会与 OpenCV 一起使用的库。因为 OpenCV 定义了一个 Point_ 类,该类在我的库将在其中使用的某些上下文中常用,所以我想添加选项以将 Point_s 作为参数传递给我的某些函数。也就是说,OpenCV 是一个非常重的库,我非常不想仅仅为了访问它的 Point_ 类而依赖它。

定义我自己的 Point_ 相同的 Point_ 类会导致预期的多重定义错误。

我考虑使用预处理器宏来检查是否已包含包含 Point_ 的 OpenCV 标头,如果尚未包含则仅定义它,但我担心如果首先包含我的库标头,则多重定义错误将返回,这将使我的库难以为我以外的任何人使用。

有没有一种方法可以提供仅在其他任何地方没有定义时才使用的定义,和/或如果确实出现在其他地方时将被覆盖?

【问题讨论】:

    标签: c++ dependencies shared-libraries multiple-definition-error


    【解决方案1】:

    您可以做的是根据 your 点类定义 your 库,并可选择为 OpenCVlibrary 类型生成 conversions,如果展示。像这样的:

    #ifdef HAVE_OPENCV
    #include <opencv2/opencv.hpp>
    #endif
    
    struct my_point
    {
        double x;
        double y;
    
    #ifdef HAVE_OPENCV
        my_point(cv::Point2d p): x(p.x), y(p.y) {}
    
        operator cv::Point2d() const { return {x, y}; }
    #endif
    };
    
    my_point my_function(my_point p)
    {
        return p;
    }
    
    int main()
    {
        cv::Point2d p;
    
        // automatic conversions happen between OpenCV version
        // and your library's version
        cv::Point2d q = my_function(p);
    }
    

    因为转换运算符是微不足道的内联函数,编译器会将它们完全优化掉,让代码就好像根本没有发生任何转换一样。

    您可以选择(最好是 imo)进行转换显式,这可能会使代码更安全:

    struct my_point
    {
        double x;
        double y;
    
    #ifdef HAVE_OPENCV
        // make these explicit
        explicit my_point(cv::Point2d p): x(p.x), y(p.y) {}
    
        explicit operator cv::Point2d() const { return {x, y}; }
    #endif
    };
    
    my_point my_function(my_point p)
    {
        return p;
    }
    
    int main()
    {
        cv::Point2d p;
    
        // Now the library user needs to explicitly ask for
        // the conversions to take place
        cv::Point2d q = cv::Point2d(my_function(my_point(p)));
    }
    

    【讨论】:

    • 我确实喜欢这种方法,但它希望我提到的其他可能的宏解决方案和@nVxx 的回答,要求我的图书馆的用户了解我的图书馆的特殊需求(定义 HAVE_OPENCV 宏),这是我试图避免的。
    【解决方案2】:

    一种解决方案是在您的项目构建配置中处理此问题:在您的构建系统中设置预处理器定义(例如COMPILE_WITH_OPENCV)。如果您使用的是CMake,则类似于

    ADD_DEFINITIONS(-DCOMPILE_WITH_OPENCV)
    

    在代码中:

    #if defined COMPILE_WITH_OPENCV
    #include "types.hpp" // openCV inlcude
    #else
    #include "my_types.hpp"  // your own Point_ definition
    #endif
    

    【讨论】:

    • 这可行,但与我提到的其他可能的宏解决方案一样,需要我图书馆的用户了解我图书馆的特殊需求,这是我试图避免的。
    • @DaggerOfMesogrecia,另一个技巧是让您自己的标头具有与 openCV 相同的标头保护(即#ifndef OPENCV_CORE_TYPES_HPP),这将有助于编写其余代码而无需任何预处理器分支,但是当您的库标头之后包含 OpenCV 标头时,此解决方案仍然会失败。而且恐怕没有预处理器/代码内解决方案可以解决这个问题。
    猜你喜欢
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 2019-04-09
    • 2020-04-24
    • 1970-01-01
    • 2021-05-18
    • 1970-01-01
    相关资源
    最近更新 更多