C ++ Как правильно выставить Shared Library через заголовок - PullRequest
0 голосов
/ 29 апреля 2019

Я спроектировал и разработал библиотеку 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, атрибуты attribute03 и attribute04 установлены правильно, и я могу использовать их до некоторой точки.

АКТУАЛЬНАЯ ЗАДАЧА С ВСЕМ ЭТОМ СЦЕНАРИЙ

Я не знаю почему, но в какой-то момент, attribute03 и attribute04 просто получают мусор, и у меня есть SIGABRT, который завершает выполнение.

РЕДАКТИРОВАНИЕ (2-й раз)

После некоторых комментариев я перешел к следующему решению 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 голосов
/ 29 апреля 2019

Заголовок, который я разработал, чтобы поделиться mylib.so с другими, похож на этот, но без личного раздела.

Заголовок, который вы используете для создания общей библиотеки .so, должен совпадать с заголовком, который вы предоставляете клиенту. У одного не может быть частных членов, а у другого их нет. Клиент не будет рассматривать закрытые члены как часть класса, но при выполнении функции он попытается использовать память, которая не принадлежит экземпляру.

Как уже упоминалось, PIMPL является широко используемым решением. В частном разделе вашего класса вы можете иметь MyClassData * mData; декларация. В вашем файле .cpp вы можете определить struct MyClassData и инициировать ее члены. В конструкторе выделите память для mData, а в деструкторе удалите память.

0 голосов
/ 29 апреля 2019

Как уже упоминалось выше, PIMPL является лучшим решением для этого.Например, Qt использует PIMPL во всех своих классах для обеспечения двоичной совместимости.То есть, когда установлена ​​более новая версия библиотеки DLL, она совместима со всеми старыми двоичными файлами, поскольку общий интерфейс не изменяется.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...