QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 
24 #include "qgsservicenativeloader.h"
25 #include "qgsservicemodule.h"
26 #include "qgsmessagelog.h"
27 #include "qgis.h"
28 
29 
30 typedef void unloadHook_t( QgsServiceModule * );
31 
39 {
40  public:
41 
46  QgsServiceNativeModuleEntry( const QString &location )
47  : mLocation( location )
48  {}
49 
50  QString mLocation;
53 };
54 
55 void 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  //QgsDebugMsg( QStringLiteral( "Loading native module %1" ).arg( location ) );
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 
147 QgsServiceNativeModuleEntry *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 
158 void 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 }
QgsServiceModule
Class defining the service module interface for QGIS server services.
Definition: qgsservicemodule.h:41
unloadHook_t
void unloadHook_t(QgsServiceModule *)
Definition: qgsservicenativeloader.cpp:30
qgis.h
QgsServiceModule::registerSelf
virtual void registerSelf(QgsServiceRegistry &registry, QgsServerInterface *serverIface=nullptr)=0
Asks the module to register all provided services.
QgsServiceNativeModuleEntry::QgsServiceNativeModuleEntry
QgsServiceNativeModuleEntry(const QString &location)
Constructor for QgsServiceNativeModuleEntry.
Definition: qgsservicenativeloader.cpp:46
QgsServiceNativeLoader::unloadModules
void unloadModules()
Unload all modules.
Definition: qgsservicenativeloader.cpp:133
serviceEntryPoint_t
QgsServiceModule * serviceEntryPoint_t()
Definition: qgsservicenativeloader.cpp:83
QgsMessageLog::logMessage
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).
Definition: qgsmessagelog.cpp:27
QgsServiceNativeModuleEntry::mUnloadHook
unloadHook_t * mUnloadHook
Definition: qgsservicenativeloader.cpp:52
QgsServiceNativeLoader::loadModules
void loadModules(const QString &modulePath, QgsServiceRegistry &registrar, QgsServerInterface *serverIface=nullptr)
Load all modules from path.
Definition: qgsservicenativeloader.cpp:55
QgsServiceNativeModuleEntry::mModule
QgsServiceModule * mModule
Definition: qgsservicenativeloader.cpp:51
QgsServiceNativeLoader::loadNativeModule
QgsServiceModule * loadNativeModule(const QString &location)
Load the native module from path.
Definition: qgsservicenativeloader.cpp:85
QgsServiceRegistry
QgsServiceRegistry Class defining the registry manager for QGIS server services.
Definition: qgsserviceregistry.h:49
cast_to_fptr
#define cast_to_fptr(f)
Definition: qgis.h:2137
QgsServiceNativeModuleEntry
Native module (location, the module itself and the unload function).
Definition: qgsservicenativeloader.cpp:38
qgsservicemodule.h
qgsservicenativeloader.h
QgsServerInterface
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
Definition: qgsserverinterface.h:60
QgsServiceNativeModuleEntry::mLocation
QString mLocation
Definition: qgsservicenativeloader.cpp:50
qgsmessagelog.h