C ++如何通过标头正确显示共享库

时间:2019-04-29 13:00:32

标签: c++ attributes shared-libraries header-files private-members

我已经设计和开发了SHARED库,并希望分发它,但是我不想公开私有方法和私有属性。

这是我尝试的没有成功的事情:

完整标头,用于构建库mylib.so:

namespace MYNAMESPACE{
    enum class MyReturnCode {
        Success = 1,
        MyRetCode01,
        MyRetCode02
    };
    class MyException {
        public:
            MyException(
                MYNAMESPACE::MyReturnCode _code,
                std::string _message);

            MYNAMESPACE::MyReturnCode code;
            std::string message;
    };
    class MyClass {
        public:     
            MyClass();
            ~MyClass();
            void initialize();
            std::string function01();
            std::string function02(); 
            int attribute01;
            float attribute02;     
        private:
            std::string function03();
            int attribute03;
            float attribute04;
    };
}

我设计用于与他人共享mylib.so时使用的标头与此相似,但没有私有部分。

当我调用函数initialize时,属性attribute03attribute04的设置正确,并且可以一直使用。

所有此情况下的实际问题

我不知道为什么,但是在某个时候,attribute03attribute04只是有些垃圾,我有一个SIGABRT结束了执行。

已编辑(第二次)

经过一番评论,我进入了以下PIMPL解决方案,现在它可以正常工作。

标头my_class_api.hpp,用于与mylib.so一起分发

#include <memory>

namespace MY_API {
    class MyClassAPI {
        public:     
            virtual ~MyClassAPI() {};
            virtual void initialize() = 0;
            virtual std::string function01() = 0;
            virtual std::string function02() = 0; 

            static std::shared_ptr<MyClassAPI> get_my_api();
    };
}

新的完整标头my_class.hpp,用于构建库mylib.so:

#include "my_class_api.hpp"

namespace MYNAMESPACE{
    class MyClass : public MY_API::MyClassAPI {
        public:     
            MyClass();
            ~MyClass() override;
            void initialize() override;
            std::string function01() override;
            std::string function02() override; 

        private:
            std::string function03();
            int attribute03;
            float attribute04;
    };
}

实施文件my_class.cpp

#include "my_class.hpp"

namespace MY_API {

    std::shared_ptr<MyClassAPI> MyClassAPI::get_my_api() {
        return std::make_shared<MYNAMESPACE::MyClass>();
    }
}

namespace MYNAMESPACE {

    MyClass::MyClass() { }
    MyClass::~MyClass() { }
    void MyClass::initialize() { }
    std::string MyClass::function01() { }
    std::string MyClass::function02() { }
}

感谢所有帮助我的人!我希望这个例子也能帮助其他人。

2 个答案:

答案 0 :(得分:0)

如上所述,PIMPL是最好的解决方案。例如,Qt在其所有类上使用PIMPL来确保二进制兼容性。也就是说,当安装了较新版本的DLL时,它与所有旧的二进制文件兼容,因为公共接口不会更改。

https://en.cppreference.com/w/cpp/language/pimpl

答案 1 :(得分:0)

  

我设计用于与他人共享mylib.so时使用的标头与此相似,但没有私有部分。

用于构建.so共享库的标头应与公开给客户端的标头相同。一个不能拥有私人成员,另一个不能拥有私人成员。客户端不会将私有成员视为类的一部分,但是在执行功能时,它将尝试使用不属于该实例的内存。

如上所述,PIMPL是一种常用的解决方案。在您班级的私有部分,您可以拥有MyClassData * mData;宣言。在您的.cpp文件中,您可以定义结构MyClassData并初始化其成员。在构造函数中,将内存分配给mData,然后在析构函数中删除该内存。