QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsservicenativeloader.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsservicerenativeloader.cpp
3
4 Define Loader for native service modules
5 -------------------
6 begin : 2016-12-05
7 copyright : (C) 2016 by David Marteau
8 email : david dot marteau at 3liz dot com
9 ***************************************************************************/
10
11/***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20#include <QLibrary>
21#include <QDir>
22#include <QDebug>
23
25#include "qgsservicemodule.h"
26#include "qgsmessagelog.h"
27#include "qgis.h"
28
29
31
39{
40 public:
41
46 QgsServiceNativeModuleEntry( const QString &location )
47 : mLocation( location )
48 {}
49
50 QString mLocation;
53};
54
55void QgsServiceNativeLoader::loadModules( const QString &modulePath, QgsServiceRegistry &registrar,
56 QgsServerInterface *serverIface )
57{
58 QDir moduleDir( modulePath );
59 moduleDir.setSorting( QDir::Name | QDir::IgnoreCase );
60 moduleDir.setFilter( QDir::Files );
61
62#if defined(Q_OS_WIN) || defined(__CYGWIN__)
63 moduleDir.setNameFilters( QStringList( "*.dll" ) );
64#else
65 moduleDir.setNameFilters( QStringList( "*.so" ) );
66#endif
67
68 // qDebug() << QString( "Checking %1 for native services modules" ).arg( moduleDir.path() );
69
70 const auto constFiList( moduleDir.entryInfoList() );
71 for ( const QFileInfo &fi : constFiList )
72 {
73 QgsServiceModule *module = loadNativeModule( fi.filePath() );
74 if ( module )
75 {
76 // Register services
77 module->registerSelf( registrar, serverIface );
78 }
79 }
80}
81
82
84
86{
87 QgsServiceNativeModuleEntry *entry = findModuleEntry( location );
88 if ( entry )
89 {
90 return entry->mModule;
91 }
92
93 QLibrary lib( location );
94 //QgsDebugMsgLevel( QStringLiteral( "Loading native module %1" ).arg( location ), 2 );
95 qDebug() << QString( "Loading native module %1" ).arg( location );
96 if ( !lib.load() )
97 {
98 QgsMessageLog::logMessage( QString( "Failed to load library %1: %2" ).arg( lib.fileName(), lib.errorString() ) );
99 return nullptr;
100 }
101 // Load entry point
103 entryPointFunc = reinterpret_cast<serviceEntryPoint_t *>( cast_to_fptr( lib.resolve( "QGS_ServiceModule_Init" ) ) );
104
105 if ( entryPointFunc )
106 {
107 QgsServiceModule *module = entryPointFunc();
108 if ( module )
109 {
110 entry = new QgsServiceNativeModuleEntry( location );
111 entry->mModule = module;
112 entry->mUnloadHook = reinterpret_cast<unloadHook_t *>( cast_to_fptr( lib.resolve( "QGS_ServiceModule_Exit" ) ) );
113
114 // Add entry
115 mModules.insert( location, ModuleTable::mapped_type( entry ) );
116 return module;
117 }
118 else
119 {
120 QgsMessageLog::logMessage( QString( "No entry point for module %1" ).arg( lib.fileName() ) );
121 }
122 }
123 else
124 {
125 QgsMessageLog::logMessage( QString( "Error: entry point returned null for %1" ).arg( lib.fileName() ) );
126 }
127
128 // No module found: release library
129 lib.unload();
130 return nullptr;
131}
132
134{
135 ModuleTable::iterator it = mModules.begin();
136 const ModuleTable::iterator end = mModules.end();
137
138 while ( it != end )
139 {
140 unloadModuleEntry( it->get() );
141 ++it;
142 }
143
144 mModules.clear();
145}
146
147QgsServiceNativeModuleEntry *QgsServiceNativeLoader::findModuleEntry( const QString &location )
148{
149 QgsServiceNativeModuleEntry *entry = nullptr;
150 const ModuleTable::iterator item = mModules.find( location );
151 if ( item != mModules.end() )
152 {
153 entry = item->get();
154 }
155 return entry;
156}
157
158void QgsServiceNativeLoader::unloadModuleEntry( QgsServiceNativeModuleEntry *entry )
159{
160 // Call cleanup function if it exists
161 if ( entry->mUnloadHook )
162 {
163 entry->mUnloadHook( entry->mModule );
164 }
165
166 QLibrary lib( entry->mLocation );
167 lib.unload();
168}
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
Class defining the service module interface for QGIS server services.
virtual void registerSelf(QgsServiceRegistry &registry, QgsServerInterface *serverIface=nullptr)=0
Asks the module to register all provided services.
QgsServiceModule * loadNativeModule(const QString &location)
Load the native module from path.
void unloadModules()
Unload all modules.
void loadModules(const QString &modulePath, QgsServiceRegistry &registrar, QgsServerInterface *serverIface=nullptr)
Load all modules from path.
Native module (location, the module itself and the unload function).
QgsServiceNativeModuleEntry(const QString &location)
Constructor for QgsServiceNativeModuleEntry.
QgsServiceRegistry Class defining the registry manager for QGIS server services.
#define cast_to_fptr(f)
Definition: qgis.h:5059
void unloadHook_t(QgsServiceModule *)
QgsServiceModule * serviceEntryPoint_t()