C++ 如何通过标头正确公开共享库
C++ How to correctly expose a Shared Library via header
我已经设计并开发了一个共享库,并希望分发它,但我不想公开私有方法和私有属性。
这是我尝试过但没有成功的方法:
完整标头,用于构建库 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() { }
}
感谢所有帮助过我的人!我希望这个例子也能帮助其他人。
如上所述,PIMPL是最好的解决方案。 例如,Qt在其所有类上使用PIMPL来确保二进制兼容性。 也就是说,当安装较新版本的 DLL 时,它与所有旧二进制文件兼容,因为公共接口不会更改。
https://en.cppreference.com/w/cpp/language/pimpl
我设计在与他人共享 mylib.so 时使用的标题与此类似,但没有私有部分。
用于生成 .so 共享库的标头应与向客户端公开的标头相同。一个不能有私人成员,另一个不能有私人成员。客户端不会将私有成员视为类的一部分,但在执行函数时,它会尝试使用不属于实例的内存。
如前所述,PIMPL是一种常用的解决方案。在班级的私人部分,您可以拥有 MyClassData* mData;声明。在.cpp文件中,可以定义结构 MyClassData,并启动其成员。在构造函数中,将内存分配给 mData,在析构函数中删除内存。
- 是否可以通过C++扩展强制多个python进程共享同一内存
- C++:在不中断共享的情况下通过引用传递共享 PTR?
- Linux 可执行文件通过 dlopen 在emplace_back崩溃打开共享库
- 尝试通过共享指针使用变量时读取访问冲突
- 通过cMake使用具有自定义文件扩展名的共享库
- 如何通过指向元组的共享指针删除对象
- 通过require在不同的Lua状态之间共享全局变量
- 通过 mmap-ed 共享内存传递可变长度 C 字符串
- 矩阵矢量产品 CUDA 通过平铺和共享内存提高性能
- 通过 Boost Python 在C++对象之间传递共享指针的隔离错误
- 通过为每个线程独占使用对象(不在线程之间共享)是保护该类的成员函数所必需的
- <T>通过引用传输向量<shared_ptr>而不绕过共享语义
- 如何通过更好的性能传递和共享共享的所有权
- 如何通过另一个类将共享指针传递给一个类?
- 多态性和共享_ptr通过引用传递
- C++ 如何通过标头正确公开共享库
- 通过线程共享 std::指针的矢量
- 如何通过共享_ptr向量迭代
- 通过引用返回共享对象是否安全"std::lock_guard<mutex>"?
- 如何通过文件映射对象重新映射共享内存的视图?