【发布时间】:2013-12-23 21:33:36
【问题描述】:
我想要一个共享库并将这个库传递给一些 Qt 插件。 Qt 插件与库/库接口一起使用(创建一些东西,编辑它们等)。 我的计划:
- 启动Qt应用程序和共享库(共享库在编译时链接,因此无需使用dlopen/LoadLibrary和resolve。应用程序只需找到该库)
- 搜索 Qt 插件并加载它们
- 将共享库传递给 Qt 插件
- 让 Qt 插件与库一起工作
整个 Qt 很清楚,并且在 Linux、Unix 和 Windows(使用 GCC 和 MSVC)下工作。请注意以下几点:
- 我来自 Java 背景。在Java中会有一个接口,一个实现接口的抽象类和一个扩展抽象类的业务类。也许是一个用于创建业务对象并将接口返回给库用户的工厂类。但是业务对象永远无法从类外部访问,因为它是包保护的
- 根据信息 1:如何使用 C++ 实现相同的功能?我的想法如下(代码在最后):
- 工厂:创建业务对象,但返回接口
- 接口:与虚函数的接口
- 业务类:实现接口
- 导出工厂和接口,但隐藏业务类
- 解决方案必须独立于平台
- 在编译时链接库,避免 dlopen/LoadLibrary & resolve
- 使业务对象只能通过接口或工厂访问
这会导致以下问题:
- 为什么
dataobject和abuseddataobjectBOTH 都可以访问?为什么不仅是工厂创建的对象(接口)(而且abuseddataobject会触发编译器错误)?这个想法是隐藏业务对象并使其只能通过接口访问并且只能由工厂创建。该库确实负责 GCC__attributes__?有什么错误/问题? - 这是在 C++ 中执行此操作的常用方法,还是我“对 Java 视而不见”(参见 C++ 代码)并将 Java 和 C++ 混为一谈?
- 如果我对 Java 视而不见,在 C++ 中执行此操作的(常见)方法是什么(请提供代码示例)?
main.cpp
#include <iostream>
#include "library/Extern.h"
#include "library/Factory.h"
#include "library/DataInterface.h"
#include "library/Data.h" // NOTE: User abuses our interface and includes the data object
int main(void)
{
// Create the factory and get an interface object
Factory factory;
DataInterface *dataobject = factory.getDataObject();
// Play around
std::cout << "Value:" << dataobject->getValue() << std::endl;
// But now someone abuses our data object ... WHY IS THIS POSSIBLE ?
Data *abuseddateobject = new Data();
std::cout << "Abused value:" << abuseddateobject->getValue() << std::endl;
// Cleanup
delete dataobject;
delete abuseddateobject;
return 0;
}
工厂.h
#ifndef FACTORY_H
#define FACTORY_H
#include "Extern.h"
#include "DataInterface.h"
#include "Data.h"
class DLL_PUBLIC Factory
{
public:
DLL_PUBLIC DataInterface *getDataObject();
};
#endif // FACTORY_H
Factory.cpp
#include "Factory.h"
DataInterface *Factory::getDataObject()
{
return new Data();
}
数据接口.h
#ifndef DATAINTERFACE_H
#define DATAINTERFACE_H
#include "Extern.h"
class DLL_PUBLIC DataInterface
{
public:
DLL_PUBLIC virtual ~DataInterface() {}
DLL_PUBLIC virtual int getValue() = 0;
};
#endif // DATAINTERFACE_H
数据.h
#ifndef DATA_H
#define DATA_H
#include "Extern.h"
#include "DataInterface.h"
class DLL_LOCAL Data : public DataInterface
{
public:
DLL_LOCAL int getValue()
{
return 42;
}
};
#endif // DATA_H
最后是 Extern.h。库构建系统 (CMake) 确实为共享库定义了 BUILDING_DLL,所以这不是问题。目前我只是在为 Linux 编写一个原型,所以 Windows 支持并不重要
外部.h
#ifndef SOMECLASSEXTERN_H
#define SOMECLASSEXTERN_H
// Taken from: http://gcc.gnu.org/wiki/Visibility
#if defined _WIN32 || defined __CYGWIN__
#ifdef BUILDING_DLL
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllexport))
#else
#define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
#endif
#else
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllimport))
#else
#define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
#endif
#endif
#define DLL_LOCAL
#else
#if __GNUC__ >= 4
#define DLL_PUBLIC __attribute__ ((visibility ("default")))
#define DLL_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define DLL_PUBLIC
#define DLL_LOCAL
#endif
#endif
#endif // SOMECLASSEXTERN_H
感谢您花时间回答这个问题
【问题讨论】:
标签: c++ qt inheritance shared-libraries libraries