Qt 플러그인 생성 방법
Qt는 플러그인 생성을 위한 두 가지 API를 제공합니다:
- 사용자 정의 데이터베이스 드라이버, 이미지 포맷, 텍스트 코덱, 사용자 정의 스타일과 같은 Qt 자체에 대한 확장을 작성하기 위한 고수준 API.
- Qt 애플리케이션 확장을 위한 로우 레벨 API.
예를 들어, 사용자 정의 QStyle 서브클래스를 작성하고 Qt 애플리케이션이 이를 동적으로 로드하도록 하려면 상위 레벨 API를 사용합니다.
상위 수준 API는 하위 수준 API 위에 구축되므로 일부 문제는 두 가지 모두에 공통적입니다.
Qt Widgets Designer 에 사용할 플러그인을 제공하려면 사용자 정의 위젯 플러그인 만들기를 참조하세요.
상위 수준 API: Qt 확장 작성하기
Qt 자체를 확장하는 플러그인을 작성하려면 적절한 플러그인 베이스 클래스를 서브 클래싱하고 몇 가지 함수를 구현한 다음 매크로를 추가하면 됩니다.
여러 플러그인 베이스 클래스가 있습니다. 파생된 플러그인은 기본적으로 표준 플러그인 디렉터리의 하위 디렉터리에 저장됩니다. 플러그인이 적절한 디렉터리에 저장되어 있지 않으면 Qt는 플러그인을 찾지 못합니다.
다음 표는 플러그인 베이스 클래스를 요약한 것입니다. 일부 클래스는 비공개이므로 문서화되어 있지 않습니다. 이러한 클래스는 사용할 수 있지만 이후 Qt 버전과의 호환성은 보장되지 않습니다.
베이스 클래스 | 디렉토리 이름 | Qt 모듈 | 키 대소문자 구분 |
---|---|---|---|
QAccessibleBridgePlugin | accessiblebridge | Qt GUI | 대소문자 구분 |
QImageIOPlugin | imageformats | Qt GUI | 대소문자 구분 |
QPictureFormatPlugin (더 이상 사용되지 않음) | pictureformats | Qt GUI | 대소문자 구분 |
QBearerEnginePlugin | bearer | Qt Network | 대소문자 구분 |
Q플랫폼인풋컨텍스트플러그인 | platforminputcontexts | Qt 플랫폼 추상화 | 대소문자 구분 없음 |
QPlatform통합 플러그인 | platforms | Qt 플랫폼 추상화 | 대소문자 구분 없음 |
QPlatformThemePlugin | platformthemes | Qt 플랫폼 추상화 | 대소문자 구분 없음 |
QPlatformPrinterSupportPlugin | printsupport | Qt Print Support | 대소문자 구분 |
QSGContextPlugin | scenegraph | Qt Quick | 대소문자 구분 |
QSqlDriverPlugin | sqldrivers | Qt SQL | 대소문자 구분 |
QIconEnginePlugin | iconengines | Qt SVG | 대소문자 구분 안 함 |
QAccessiblePlugin | accessible | Qt Widgets | 대소문자 구분 |
QStylePlugin | styles | Qt Widgets | 대소문자 구분 안 함 |
플러그인으로 사용할 수 있도록 하려는 JsonViewer
이라는 새 문서 뷰어 클래스가 있는 경우 클래스를 다음과 같이 정의해야 합니다(jsonviewer.h
):
class JsonViewer : public ViewerInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.DocumentViewer.ViewerInterface/1.0" FILE "jsonviewer.json") Q_INTERFACES(ViewerInterface) public: JsonViewer(); ~JsonViewer() override; private: bool openJsonFile(); QTreeView *m_tree; QListWidget *m_toplevel = nullptr; QJsonDocument m_root; QPointer<QLineEdit> m_searchKey; };
클래스 구현이 .cpp
파일에 있는지 확인하세요:
JsonViewer::JsonViewer() { connect(this, &AbstractViewer::uiInitialized, this, &JsonViewer::setupJsonUi); } void JsonViewer::init(QFile *file, QWidget *parent, QMainWindow *mainWindow) { AbstractViewer::init(file, new QTreeView(parent), mainWindow); m_tree = qobject_cast<QTreeView *>(widget()); }
또한 대부분의 플러그인에는 플러그인을 설명하는 메타 데이터가 포함된 json 파일(jsonviewer.json
)이 필요합니다. 문서 뷰어 플러그인의 경우 뷰어 플러그인의 이름만 포함하면 됩니다.
{ "Keys": [ "jsonviewer" ] }
json 파일에 제공해야 하는 정보의 유형은 플러그인에 따라 다릅니다. 파일에 포함해야 하는 정보에 대한 자세한 내용은 클래스 설명서를 참조하세요.
데이터베이스 드라이버, 이미지 형식, 텍스트 코덱 및 기타 대부분의 플러그인 유형의 경우 명시적인 객체 생성이 필요하지 않습니다. Qt가 필요에 따라 찾아서 생성합니다.
플러그인 클래스는 추가 함수를 구현해야 할 수도 있습니다. 각 플러그인 유형에 대해 다시 구현해야 하는 가상 함수에 대한 자세한 내용은 클래스 설명서를 참조하세요.
문서 뷰어 데모는 파일의 구조화된 콘텐츠를 표시하는 플러그인을 구현하는 방법을 보여줍니다. 따라서 각 플러그인은 다음과 같은 가상 함수를 다시 구현합니다.
- 플러그인을 식별하고
- 지원하는 MIME 유형을 반환하고
- 표시할 콘텐츠가 있는지 여부를 알려주고
- 콘텐츠 표시 방법
QString viewerName() const override { return QLatin1StringView(staticMetaObject.className()); }; QStringList supportedMimeTypes() const override; bool hasContent() const override; bool supportsOverview() const override { return true; }
로우 레벨 API: Qt 애플리케이션 확장하기
Qt 자체 외에도 플러그인을 통해 Qt 애플리케이션을 확장할 수 있습니다. 이를 위해서는 애플리케이션이 QPluginLoader 를 사용하여 플러그인을 감지하고 로드해야 합니다. 이러한 맥락에서 플러그인은 임의의 기능을 제공할 수 있으며, 데이터베이스 드라이버, 이미지 포맷, 텍스트 코덱, 스타일 및 Qt의 기능을 확장하는 기타 유형의 플러그인에 국한되지 않습니다.
플러그인을 통해 애플리케이션을 확장 가능하게 만드는 작업은 다음 단계를 포함합니다:
- 플러그인과 통신하는 데 사용되는 인터페이스 세트(순수 가상 함수만 있는 클래스)를 정의합니다.
- Q_DECLARE_INTERFACE() 매크로를 사용하여 Qt의 메타 객체 시스템에 인터페이스에 대해 알립니다.
- 애플리케이션에서 QPluginLoader 을 사용하여 플러그인을 로드합니다.
- qobject_cast()를 사용하여 플러그인이 주어진 인터페이스를 구현하는지 테스트합니다.
플러그인 작성에는 이러한 단계가 포함됩니다:
- QObject 및 플러그인이 제공하고자 하는 인터페이스를 상속하는 플러그인 클래스를 선언합니다.
- Q_INTERFACES() 매크로를 사용하여 Qt의 메타 객체 시스템에 인터페이스에 대해 알립니다.
- Q_PLUGIN_METADATA() 매크로를 사용하여 플러그인을 내보냅니다.
예를 들어 다음은 인터페이스 클래스의 정의입니다:
class ViewerInterface : public AbstractViewer { public: virtual ~ViewerInterface() = default; };
다음은 인터페이스 선언입니다:
#define ViewerInterface_iid "org.qt-project.Qt.Examples.DocumentViewer.ViewerInterface/1.0" Q_DECLARE_INTERFACE(ViewerInterface, ViewerInterface_iid)
Qt Widgets Designer 에 특정한 문제에 대한 정보는 Qt Widgets Designer 에 대한 사용자 정의 위젯 만들기를 참조하세요.
플러그인 찾기
플러그인은 표준 플러그인 하위 디렉터리에 저장되기 때문에 Qt 응용 프로그램은 어떤 플러그인을 사용할 수 있는지 자동으로 알 수 있습니다. 따라서 Qt는 플러그인을 자동으로 처리하므로 응용 프로그램에서 플러그인을 찾아서 로드하는 데 코드를 작성할 필요가 없습니다.
개발 중 플러그인 디렉토리는 QTDIR/plugins
(여기서 QTDIR
은 Qt가 설치된 디렉토리)이며, 각 플러그인 유형은 해당 유형의 하위 디렉터리(예: styles
)에 저장됩니다. 애플리케이션이 플러그인을 사용하고 표준 플러그인 경로를 사용하지 않으려면 설치 과정에서 플러그인에 사용할 경로를 결정하고 애플리케이션이 실행될 때 읽을 수 있도록 QSettings 을 사용하여 경로를 저장합니다. 그러면 애플리케이션에서 이 경로로 QCoreApplication::addLibraryPath()를 호출하면 애플리케이션에서 플러그인을 사용할 수 있습니다. 경로의 마지막 부분(예: styles
)은 변경할 수 없다는 점에 유의하세요.
플러그인을 로드할 수 있게 하려면 애플리케이션 아래에 하위 디렉터리를 만들고 해당 디렉터리에 플러그인을 배치하는 것도 한 가지 방법입니다. Qt와 함께 제공되는 플러그인( plugins
디렉터리에 있는 플러그인)을 배포하는 경우 플러그인이 있는 plugins
아래에 있는 하위 디렉터리를 애플리케이션 루트 폴더에 복사해야 합니다(즉, plugins
디렉터리는 포함하지 말아야 합니다).
배포에 대한 자세한 내용은 Qt 애플리케이션 배포 및 플러그인 배포 문서를 참조하십시오.
정적 플러그인
애플리케이션에 플러그인을 포함시키는 가장 일반적이고 유연한 방법은 별도로 제공되는 동적 라이브러리로 컴파일하여 런타임에 감지 및 로드하는 것입니다.
플러그인은 애플리케이션에 정적으로 링크할 수 있습니다. 정적 버전의 Qt를 빌드하는 경우, 이는 Qt의 사전 정의된 플러그인을 포함할 수 있는 유일한 옵션입니다. 정적 플러그인을 사용하면 배포 시 오류가 덜 발생하지만 애플리케이션을 완전히 다시 빌드하고 재배포하지 않으면 플러그인의 기능을 추가할 수 없다는 단점이 있습니다.
CMake와 qmake는 사용되는 Qt 모듈에 일반적으로 필요한 플러그인을 자동으로 추가하지만, 보다 전문적인 플러그인은 수동으로 추가해야 합니다. 자동으로 추가되는 플러그인의 기본 목록은 유형별로 재정의할 수 있습니다.
기본값은 최적의 즉시 사용 환경을 위해 조정되어 있지만 애플리케이션을 불필요하게 부풀릴 수 있습니다. 링커 명령줄을 검사하여 불필요한 플러그인을 제거하는 것이 좋습니다.
정적 플러그인이 실제로 링크되고 인스턴스화되도록 하려면 애플리케이션 코드에 Q_IMPORT_PLUGIN() 매크로도 필요하지만 빌드 시스템에서 자동으로 생성되어 애플리케이션 프로젝트에 추가됩니다.
CMake에서 정적 플러그인 가져오기
CMake 프로젝트에서 플러그인을 정적으로 링크하려면 qt_import_plugins 명령을 호출해야 합니다.
예를 들어 Linux libinput
플러그인은 기본적으로 임포트되지 않습니다. 다음 명령은 이를 임포트합니다:
qt_import_plugins(myapp INCLUDE Qt::QLibInputPlugin)
기본 Qt Platform Adaptation 플러그인 대신 최소 플랫폼 통합 플러그인을 연결하려면 다음을 사용합니다:
qt_import_plugins(myapp INCLUDE_BY_TYPE platforms Qt::MinimalIntegrationPlugin )
또 다른 일반적인 사용 사례는 특정 imageformats
플러그인 세트만 연결하는 것입니다:
qt_import_plugins(myapp INCLUDE_BY_TYPE imageformats Qt::QJpegPlugin Qt::QGifPlugin )
imageformats
플러그인의 연결을 막으려면 다음을 사용하세요:
qt_import_plugins(myapp EXCLUDE_BY_TYPE imageformats )
기본 플러그인 추가를 해제하려면 qt_import_plugins의 NO_DEFAULT
옵션을 사용하세요.
qmake에서 정적 플러그인 임포트하기
qmake 프로젝트에서는 QTPLUGIN
을 사용하여 필요한 플러그인을 빌드에 추가해야 합니다:
QTPLUGIN += qlibinputplugin
예를 들어 기본 Qt Platform Adaptation 플러그인 대신 최소 플러그인을 연결하려면 다음을 사용합니다:
QTPLUGIN.platforms = qminimal
기본 플러그인이나 최소 플러그인 모두 자동으로 연결하지 않으려면 다음을 사용합니다:
QTPLUGIN.platforms = -
QTPLUGIN에 추가된 모든 플러그인이 자동으로 연결되지 않도록 하려면 CONFIG
변수에서 import_plugins
을 제거하세요:
CONFIG -= import_plugins
정적 플러그인 생성하기
다음 단계에 따라 자신만의 정적 플러그인을 만들 수도 있습니다:
CMakeLists.txt
에서 qt_add_plugin 명령에STATIC
옵션을 전달합니다. qmake 프로젝트의 경우, 플러그인의.pro
파일에CONFIG += static
을 추가합니다.- 애플리케이션에서 Q_IMPORT_PLUGIN() 매크로를 사용합니다.
- 플러그인이 qrc 파일을 제공하는 경우 애플리케이션에서 Q_INIT_RESOURCE() 매크로를 사용합니다.
CMakeLists.txt
또는LIBS
파일의.pro
에서 target_link_libraries를 사용하여 애플리케이션을 플러그인 라이브러리와 연결합니다.
자세한 방법은 플러그 앤 페인트 예제 및 관련 기본 도구 플러그인을 참조하세요.
참고: 플러그인을 빌드할 때 CMake 또는 qmake를 사용하지 않는 경우 QT_STATICPLUGIN
전처리기 매크로가 정의되어 있는지 확인해야 합니다.
플러그인 로드하기
플러그인 유형(정적 또는 공유) 및 운영 체제에 따라 플러그인을 찾고 로드하는 데 특정한 접근 방식이 필요합니다. 플러그인 로딩을 위한 추상화를 구현하는 것이 유용합니다.
void ViewerFactory::loadViewerPlugins() { if (!m_viewers.isEmpty()) return;
QPluginLoader::staticInstances()는 정적으로 연결된 각 플러그인에 대한 포인터와 함께 QObjectList 를 반환합니다.
// Load static plugins const QObjectList &staticPlugins = QPluginLoader::staticInstances(); for (auto *plugin : staticPlugins) addViewer(plugin);
공유 플러그인은 배포 디렉토리에 상주하므로 OS별 처리가 필요할 수 있습니다.
// 공유 플러그인 로드 QDir pluginsDir = QDir(QApplication::applicationDirPath());#if defined(Q_OS_WINDOWS)pluginsDir.cd("app"_L1);#elif defined(Q_OS_DARWIN) if (pluginsDir.dirName()== "MacOS"_L1) { pluginsDir.cdUp(); pluginsDir.cdUp(); pluginsDir.cdUp(); }#endif const auto entryList = pluginsDir.entryList(QDir::Files); for(const QString &fileName: entryList) { QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); QObject *plugin = loader.instance(); if (plugin) addViewer(plugin);#if 0 else qDebug() << loader.errorString(); #endif} }
플러그인 배포 및 디버깅
플러그인 배포 하기 문서에서는 애플리케이션과 함께 플러그인을 배포하고 문제가 발생했을 때 디버깅하는 프로세스에 대해 설명합니다.
QPluginLoader 및 QLibrary 을참조하세요 .
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.