QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
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
21
22#include "qgis.h"
23#include "qgsmessagelog.h"
24#include "qgsservicemodule.h"
25
26#include <QDebug>
27#include <QDir>
28#include <QLibrary>
29#include <QString>
30
31using namespace Qt::StringLiterals;
32
34
42{
43 public:
48 QgsServiceNativeModuleEntry( const QString &location )
49 : mLocation( location )
50 {}
51
52 QString mLocation;
55};
56
57void QgsServiceNativeLoader::loadModules( const QString &modulePath, QgsServiceRegistry &registrar, QgsServerInterface *serverIface )
58{
59 QDir moduleDir( modulePath );
60 moduleDir.setSorting( QDir::Name | QDir::IgnoreCase );
61 moduleDir.setFilter( QDir::Files );
62
63#if defined( Q_OS_WIN ) || defined( __CYGWIN__ )
64 moduleDir.setNameFilters( QStringList( "*.dll" ) );
65#else
66 moduleDir.setNameFilters( QStringList( "*.so" ) );
67#endif
68
69 // qDebug() << QString( "Checking %1 for native services modules" ).arg( moduleDir.path() );
70
71 const auto constFiList( moduleDir.entryInfoList() );
72 for ( const QFileInfo &fi : constFiList )
73 {
74 QgsServiceModule *module = loadNativeModule( fi.filePath() );
75 if ( module )
76 {
77 // Register services
78 module->registerSelf( registrar, serverIface );
79 }
80 }
81}
82
83
85
87{
88 QgsServiceNativeModuleEntry *entry = findModuleEntry( location );
89 if ( entry )
90 {
91 return entry->mModule;
92 }
93
94 QLibrary lib( location );
95 //QgsDebugMsgLevel( u"Loading native module %1"_s.arg( location ), 2 );
96 qDebug() << QString( "Loading native module %1" ).arg( location );
97 if ( !lib.load() )
98 {
99 QgsMessageLog::logMessage( QString( "Failed to load library %1: %2" ).arg( lib.fileName(), lib.errorString() ) );
100 return nullptr;
101 }
102 // Load entry point
104 entryPointFunc
105 = reinterpret_cast<serviceEntryPoint_t *>( cast_to_fptr( lib.resolve( "QGS_ServiceModule_Init" ) ) );
106
107 if ( entryPointFunc )
108 {
109 QgsServiceModule *module = entryPointFunc();
110 if ( module )
111 {
112 entry = new QgsServiceNativeModuleEntry( location );
113 entry->mModule = module;
114 entry->mUnloadHook = reinterpret_cast<unloadHook_t *>( cast_to_fptr( lib.resolve( "QGS_ServiceModule_Exit" ) ) );
115
116 // Add entry
117 mModules.insert( location, ModuleTable::mapped_type( entry ) );
118 return module;
119 }
120 else
121 {
122 QgsMessageLog::logMessage( QString( "No entry point for module %1" ).arg( lib.fileName() ) );
123 }
124 }
125 else
126 {
127 QgsMessageLog::logMessage( QString( "Error: entry point returned null for %1" ).arg( lib.fileName() ) );
128 }
129
130 // No module found: release library
131 lib.unload();
132 return nullptr;
133}
134
136{
137 ModuleTable::iterator it = mModules.begin();
138 const ModuleTable::iterator end = mModules.end();
139
140 while ( it != end )
141 {
142 unloadModuleEntry( it->get() );
143 ++it;
144 }
145
146 mModules.clear();
147}
148
149QgsServiceNativeModuleEntry *QgsServiceNativeLoader::findModuleEntry( const QString &location )
150{
151 QgsServiceNativeModuleEntry *entry = nullptr;
152 const ModuleTable::iterator item = mModules.find( location );
153 if ( item != mModules.end() )
154 {
155 entry = item->get();
156 }
157 return entry;
158}
159
160void QgsServiceNativeLoader::unloadModuleEntry( QgsServiceNativeModuleEntry *entry )
161{
162 // Call cleanup function if it exists
163 if ( entry->mUnloadHook )
164 {
165 entry->mUnloadHook( entry->mModule );
166 }
167
168 QLibrary lib( entry->mLocation );
169 lib.unload();
170}
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Defines interfaces exposed by QGIS Server and made available to plugins.
Defines the service module interface for QGIS server 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.
A registry manager for QGIS server services.
#define cast_to_fptr(f)
Definition qgis.h:6752
void unloadHook_t(QgsServiceModule *)
QgsServiceModule * serviceEntryPoint_t()