Qt5의 플러그인 메커니즘 (1) - Qt 프레임워크의 플러그인 로드 메커니즘 개요

10515 단어
개술
Qt의 원본 코드에서 QFactory, QPlugin, Q 등 세 가지 종류를 통해 Qt의 플러그인 불러오는 메커니즘을 실현했다. 이 메커니즘은 특정한 종류의 플러그인을 불러오는 데 사용할 수 있다.
예를 들어 QPlatformIntegrationFactory\QPlatformIntegrationPlugin\QPlatformIntegration 세 가지 클래스를 통해 플랫폼 클래스인 QPA 플러그인(PlatformIntegration)을 불러올 수 있고, QPlatformInputContextFactory\QPlatformInputContextInpugin\QPlatformInputContext 세 가지 클래스를 통해 입력법 클래스 플러그인(InputContext)을 불러올 수 있다.다음은 Qt의 플러그인 로드 메커니즘을 위에서 설명합니다.
플러그인 실현: Q클래스와 QPlugin클래스는 먼저 Q클래스(또는 그 하위 클래스)는 상세한 기능을 실현한다. 그는 플러그인의 주체이고 서로 다른 종류의 플러그인은 서로 다른 기능을 실현해야 한다.
QPlugin 클래스(또는 하위 클래스)는 이 플러그인의 인터페이스 클래스입니다. 일반적으로 하나의 방법만 실현해야 합니다. creat,
class QPlugin 
{
    ...
    Q * creat(...) ;    //     Q     。           easy,
                    //         new    Q     ,      
}

QPlugin 클래스는 주로 Qt 프레임워크 자체에서 플러그인을 로드하는 데 사용됩니다.
플러그인 불러오기: QFactoryLoader 클래스와 다른 클래스입니다. 플러그인 불러오기와 밀접한 관계가 있습니다. 이 클래스는 QFactoryLoader입니다. 우리는 이 클래스의 instance () 방법에만 관심을 가져야 합니다.
QFactoryLoader::QObject *instance(int index)

QFactoryLoader 클래스는 라이브러리 목록을 유지합니다. index는 불러올 플러그인에 속하는 라이브러리의 라이브러리 목록에 있는 인덱스입니다.
instance는 QOjbect 클래스나 하위 클래스의 바늘을 되돌려줍니다. 이 바늘은 보통 QPlugin 형식으로 비칩니다.이렇게 되면Qt 프레임워크에서 플러그인을 불러올 때, 먼저 QFactoryLoader: instance (index) 를 호출해서 플러그인에 해당하는 QPlugin 포인터를 되돌려야 합니다.이 포인터를 통해 QPlugin::creat (...) 호출방법은 플러그인 주체 클래스 Q의 실례를 얻을 수 있습니다.
플러그인을 불러오는 단축 함수에 이어 qLoadPlugin과 qLoadPlugin1 두 템플릿 함수의 실현을 살펴보자. 양자 기능의 주요 차이점은 플러그인을 불러올 때의 파라미터를 설정할 수 있다는 것이다.
이 두 템플릿 함수를 사용하면 플러그인을 신속하게 불러오고 실제 예를 얻을 수 있습니다.
두 템플릿을 사용할 때 템플릿 유형 매개변수 PluginInterface는 Q(플러그인 벌크 클래스), 유형 매개변수FactoryInterface로 채워져야 합니다.
QPlugin 클래스로 채워야 합니다.
template 
    PluginInterface *qLoadPlugin(const QFactoryLoader *loader, const QString &key)
{
    const int index = loader->indexOf(key);    //      keyword                 
    if (index != -1) {
        QObject *factoryObject = loader->instance(index);    //         
        if (FactoryInterface *factory = qobject_cast(factoryObject))
            if (PluginInterface *result = factory->create(key))
                return result;    //         
    }
    return 0;
}

template 
PluginInterface *qLoadPlugin1(const QFactoryLoader *loader,
                              const QString &key,
                              const Parameter1 ¶meter1)
{
    const int index = loader->indexOf(key);
    if (index != -1) {
        QObject *factoryObject = loader->instance(index);
        if (FactoryInterface *factory = qobject_cast(factoryObject))
            if (PluginInterface *result = factory->create(key, parameter1))
                return result;
    }
    return 0;
}

플러그인 생산자: QFactory 클래스는 마지막으로 QFactory 클래스를 볼 때 Qt의 플러그인 불러오는 메커니즘 중 최상층에 있는 클래스로 이 클래스는 일반적으로 두 가지를 실현한다.
정적 방법 (우리는 creat에 더 관심이 있다), 그리고 모두 정적 이다.
그 정의는 대체로 다음과 같다.
class QFactory
{
public:
    static QStringList keys(...) ;    //     Q         keyword  ,
                    // keyword                ,  keyword       
                    //             。  QPlatformInputContextFactory::keys(...)
                    //                。
    
    static Q * creat(...) ;    //     Q     (         )    
}

QFactory::creat(...) 함수에서 환경 변수를 검출하는 등 수단을 통해 대응하는 플러그인과 관련된 키워드를 얻을 수 있다.그리고 이 키워드로 할게요.
플러그인을 불러오는 qLoadPlugin/qLoadPlugin1 또는 비슷한 방법을 호출합니다.마지막으로 플러그인 실체 클래스를 되돌려줍니다.
하나의 QFactory 클래스는 종종 특정한 클래스, 또는 특정한 기능에 해당하는 플러그인입니다.
예를 들어 QPlatformIntegrationFactory는'생산'플랫폼 클래스 플러그인에 사용됩니다.QPlatformInputContextFactory는 '생산' 입력 플러그인에 사용됩니다.일반적인 상황에서 Q팩토리 클래스에는 실제 멤버 변수가 없다.단지 몇 가지 정적 방법만 있기 때문에 Qt 프로그램에서 이 종류를 실례화할 필요가 없다.이런 정태적인 방법을 직접 사용한다.또한 Qt는 모든 QFactory 클래스에 QFactory Loader 대상을 연결합니다. 이 대상은 이 종류의 플러그인을 불러오는 것을 전담합니다.Qt 프레임워크의 맨 위에 플러그인을 불러올 때 해당하는 QFactory 클래스와 접촉만 하면 됩니다.
예를 들다.Qt 애플리케이션을 초기화하는 동안
입력기 플러그인이 필요하면 QPlatformInputContextFactory::creat (...)입력 플러그인을 생산합니다.이 플러그인을 불러오는 과정의 세부 사항에 관여하지 마십시오.
되돌아오는 이 입력법 플러그인은 도대체 무엇입니까?아이버스예요?아니면 fcitx?
이러한 모든 것은 사용자가 환경 변수 QT 를 통해 수행합니다.IM_MODULE 지정,
QPlatformInputContextFactory::create () 방법에서 이 환경 변수를 검사합니다.
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
부1: Qt 응용 프로그램의 플랫폼 클래스 플러그인 QPlatformIntegration 불러오는 과정
현재 임시로 QGuiApplicationPrivate::platformIntegration () 에 초점을 옮깁니다. 이 방법의 정의는 다음과 같습니다.
    static QPlatformIntegration *platform_integration;
    static QPlatformIntegration *platformIntegration()
    { return platform_integration; }

보기platformintegration은 현재의 실행 플랫폼을 가리키는데 이 대표 플랫폼의 구성원은 어디에서 초기화됩니까?
QGuiApplication 클래스 (GUI 프로그램마다 하나의 실례가 있음) 의 구조 함수에 있습니다.QGuiApplicationPrivate 클래스의 init() 메서드가 호출됩니다.
QGuiApplicationPrivate::init는 QGuiApplicationPrivate::createPlatformIntegration()을 호출하고 후자는 읽습니다.
QT_QPA_PLATFORM_PLUGIN_PATH\QT_QPA_PLATFORM\QT_QPA_PLATFORMTHEME와 같은 환경 변수를
init_platform(...)함수, 이 함수는 qtbase/src/gui/kernel/qguiapplication에 정의됩니다.cpp 파일에는
GuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name,
arguments, argc, argv, platformPluginPath);
....

QPlatformIntegrationFactory::create에서 플랫폼 플러그인을 불러옵니다
QPlatformIntegration *ret = loadIntegration(directLoader(), platform, paramList, argc, argv))

loadIntegration 함수는 qtbase/src/gui/kernel/QPlatformIntegrationFactory에 정의됩니다.cpp에서 이 함수의 작용과 실현 방법은 모두 템플릿 함수 qLoadPlugin의 실현과 유사하다.
static inline QPlatformIntegration *loadIntegration(QFactoryLoader *loader, const QString &key, const QStringList ¶meters, int &argc, char ** argv)
{
    const int index = loader->indexOf(key);
    if (index != -1) {

    // factory              。 QLinuxFbIntegrationPlugin ;
    //      creat          QPlatformIntegration        ,
    //            QGuiApplicationPrivate::platform_integration, 
    //                .
    //         。        QPA    ,       QPlatformIntegrationPlugin    QPlatformIntegration    。
        if (QPlatformIntegrationPlugin *factory = qobject_cast(loader->instance(index)))    
            if (QPlatformIntegration *result = factory->create(key, parameters, argc, argv))
                return result;
    }
    return 0;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
첨부 2: Qt 프로그램의 입력 클래스 플러그인 QPlatform InputContext 불러오는 과정
Linuxxcb 플랫폼이나 linuxfb 플랫폼은 플랫폼 플러그인(QXcbIntegration 또는QLinuxFbIntegration 클래스)의 initialize () 함수를 통과합니다
QPlatform InputContextFactory::create () 를 호출하여 플랫폼의 입력법 플러그인 (QPlatform InputContext 클래스) 을 초기화합니다.
QPlatformInputContextFactory::create()의 구현은 다음과 같습니다.
QPlatformInputContext *QPlatformInputContextFactory::create()
{
    QPlatformInputContext *ic = 0;

    QString icString = QString::fromLatin1(qgetenv("QT_IM_MODULE"));    //       QT_IM_MODULE。              

    if (icString == QLatin1String("none"))
        return 0;

    ic = create(icString);    //       create         
    if (ic && ic->isValid())
        return ic;

    //          
    delete ic;
    ic = 0;

    QStringList k = keys();
    for (int i = 0; i < k.size(); ++i) {
        if (k.at(i) == icString)
            continue;
        ic = create(k.at(i));
        if (ic && ic->isValid())
            return ic;
        delete ic;
        ic = 0;
    }

    return 0;

}

QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key)
{
    QStringList paramList = key.split(QLatin1Char(':'));
    const QString platform = paramList.takeFirst().toLower();

#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
    if (QPlatformInputContext *ret = qLoadPlugin1(loader(), platform, paramList))    //   key(    )           (    QPlatformInputContext     )。
        return ret;
#endif
    return 0;
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
첨부 3: 몇 가지 팁
<1>
Qt에서 라이브러리나 플러그인을 불러올 수 있는 몇 가지 종류: QLibrary, QPluginLoader, QFactoryLoader, QStaticPlugin(임시로 이것을 연구하지 않음) QLibrary와 QPluginLoader가 의존하는'사유 데이터 클래스'는 모두 QLibraryPrivate이다.하나의 QLibrary 또는 QPluginLoader의 대상은 모두 하나의 QLibraryPrivate 대상이고 그에 상응하는 라이브러리나 플러그인이 있다.QFactory Loader가 의존하는'사유 데이터 클래스'는 QFactory Loader Private이지만 QFactory Loader Private 클래스에는 QLibrary Private 목록이 포함되어 있습니다.이 목록에는 여러 QLibraryPrivate 유형의 요소가 있습니다.상응하는 일련의 라이브러리나 플러그인;그래서 QLibraryPrivate는 Qt에서 라이브러리나 플러그인과 관련된 핵심 데이터 클래스로 모든 라이브러리에 해당하는 QLibraryPrivate 대상이다.
   <2> 1. Qt Assistant에서 How to Create Qt Plugins를 검색하면 플러그인을 만드는 방법이 구체적으로 설명됩니다.주로 고급 API(Higher-level API)와 저급 API(Lower-level API) 두 가지 API가 플러그인을 쓸 수 있다.고급 API 사용법은 Qt 소스 코드에서 매우 많은 인스턴스를 볼 수 있습니다.하위 API의 사용 프레젠테이션 예제는 이 시리즈의 마지막 부분에 나와 있습니다.
2. 플러그인을 쓰지 않는다고 가정한다.Qt Assistant에서 qmake Manual을 검색할 수 있는 프로 파일입니다. 이 페이지에는 프로젝트 파일을 작성하는 것과 관련된 링크가 매우 많습니다. 예를 들어 qmake Language 링크와 같습니다.프로 파일의 문법,Variables 링크 설명.프로 파일의 변수(예를 들어 QT,CONFIG,TEMPLATE 등), Replace Functions와 Replace Functions 링크는 내장된 함수를 말한다(.pro 파일에서 사용할 수 있다)

좋은 웹페이지 즐겨찾기