Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
savoirfairelinux
jami-daemon
Commits
3cc24f26
Commit
3cc24f26
authored
Feb 02, 2009
by
Emmanuel Milou
Browse files
Add a library manager + exception handling;
Remove namespace
parent
71e71378
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/plug-in/Makefile.am
View file @
3cc24f26
...
...
@@ -5,5 +5,6 @@ noinst_LTLIBRARIES = libplugin.la
SUBDIRS
=
test
libplugin_la_SOURCES
=
\
pluginmanager.cpp
pluginmanager.cpp
\
librarymanager.cpp
src/plug-in/librarymanager.cpp
0 → 100644
View file @
3cc24f26
#include
"librarymanager.h"
LibraryManager
::
LibraryManager
(
const
std
::
string
&
filename
)
:
_filename
(
filename
),
_handlePtr
(
NULL
)
{
_handlePtr
=
loadLibrary
(
filename
);
}
LibraryManager
::~
LibraryManager
(
void
)
{
unloadLibrary
();
}
LibraryManager
::
LibraryHandle
LibraryManager
::
loadLibrary
(
const
std
::
string
&
filename
)
{
LibraryHandle
pluginHandlePtr
=
NULL
;
const
char
*
error
;
_debug
(
"Loading dynamic library %s
\n
"
,
filename
.
c_str
());
/* Load the library */
pluginHandlePtr
=
dlopen
(
filename
.
c_str
(),
RTLD_LAZY
);
if
(
!
pluginHandlePtr
)
{
error
=
dlerror
();
_debug
(
"Error while opening plug-in: %s
\n
"
,
error
);
return
NULL
;
}
dlerror
();
return
pluginHandlePtr
;
}
int
LibraryManager
::
unloadLibrary
()
{
if
(
_handlePtr
==
NULL
)
return
1
;
_debug
(
"Unloading dynamic library ...
\n
"
);
dlclose
(
_handlePtr
);
if
(
dlerror
())
{
_debug
(
"Error unloading the library : %s
\n
..."
,
dlerror
());
return
1
;
}
return
0
;
}
int
LibraryManager
::
resolveSymbol
(
const
std
::
string
&
symbol
,
SymbolHandle
*
symbolPtr
)
{
SymbolHandle
sy
=
0
;
if
(
_handlePtr
){
try
{
sy
=
dlsym
(
_handlePtr
,
symbol
.
c_str
());
if
(
sy
!=
NULL
)
{
*
symbolPtr
=
sy
;
return
0
;
}
}
catch
(...)
{}
throw
LibraryManagerException
(
_filename
,
symbol
,
LibraryManagerException
::
symbolNotFound
);
}
else
return
1
;
}
/************************************************************************************************/
LibraryManagerException
::
LibraryManagerException
(
const
std
::
string
&
libraryName
,
const
std
::
string
&
details
,
Reason
reason
)
:
_reason
(
reason
),
_details
(
""
),
std
::
runtime_error
(
""
)
{
if
(
_reason
==
loadingFailed
)
_details
=
"Error when loading "
+
libraryName
+
"
\n
"
+
details
;
else
_details
=
"Error when resolving symbol "
+
details
+
" in "
+
libraryName
;
}
const
char
*
LibraryManagerException
::
what
()
const
throw
()
{
return
_details
.
c_str
();
}
src/plug-in/librarymanager.h
0 → 100644
View file @
3cc24f26
#ifndef LIBRARY_MANAGER_H
#define LIBRARY_MANAGER_H
#include
"dlfcn.h"
#include
<stdexcept>
#include
"global.h"
class
LibraryManager
{
public:
typedef
void
*
LibraryHandle
;
typedef
void
*
SymbolHandle
;
LibraryManager
(
const
std
::
string
&
filename
);
~
LibraryManager
(
void
);
int
resolveSymbol
(
const
std
::
string
&
symbol
,
SymbolHandle
*
ptr
);
int
unloadLibrary
(
void
);
protected:
LibraryHandle
loadLibrary
(
const
std
::
string
&
filename
);
private:
std
::
string
_filename
;
LibraryHandle
_handlePtr
;
};
class
LibraryManagerException
:
public
std
::
runtime_error
{
public:
typedef
enum
Reason
{
loadingFailed
=
0
,
symbolNotFound
}
Reason
;
LibraryManagerException
(
const
std
::
string
&
libraryName
,
const
std
::
string
&
details
,
Reason
reason
);
~
LibraryManagerException
(
void
)
throw
()
{}
inline
Reason
getReason
(
void
)
{
return
_reason
;
}
const
char
*
what
()
const
throw
();
private:
Reason
_reason
;
std
::
string
_details
;
};
#endif // LIBRARY_MANAGER_H
src/plug-in/plugin.h
View file @
3cc24f26
...
...
@@ -4,40 +4,39 @@
#include
<string>
#include
"global.h"
#include
"pluginmanager.h"
/*
* @file plugin.h
* @brief Define a plugin object
*/
namespace
sflphone
{
class
Plugin
{
class
Plugin
{
public:
Plugin
(
const
std
::
string
&
name
){
_name
=
name
;
}
public:
Plugin
(
const
std
::
string
&
name
){
_name
=
name
;
}
virtual
~
Plugin
()
{}
virtual
~
Plugin
()
{
}
inline
std
::
string
getPluginName
(
void
)
{
return
_name
;
}
inline
std
::
string
getPluginName
(
void
)
{
return
_name
;
}
/**
* Return the minimal core version required so that the plugin could work
* @return int The version required
*/
virtual
int
initFunc
(
PluginInfo
**
info
)
=
0
;
/**
* Return the minimal core version required so that the plugin could work
* @return int The version required
*/
virtual
int
initFunc
(
int
i
)
=
0
;
private:
Plugin
&
operator
=
(
const
Plugin
&
plugin
);
private:
Plugin
&
operator
=
(
const
Plugin
&
plugin
);
std
::
string
_name
;
};
std
::
string
_name
;
};
}
typedef
::
sflphone
::
Plugin
*
createFunc
(
void
);
typedef
Plugin
*
createFunc
(
void
);
typedef
void
destroyFunc
(
::
sflphone
::
Plugin
*
);
typedef
void
destroyFunc
(
Plugin
*
);
#endif //PLUGIN_H
src/plug-in/pluginmanager.cpp
View file @
3cc24f26
...
...
@@ -3,10 +3,10 @@
#include
"pluginmanager.h"
::
sflphone
::
PluginManager
*
::
sflphone
::
PluginManager
::
_instance
=
0
;
PluginManager
*
PluginManager
::
_instance
=
0
;
::
sflphone
::
PluginManager
*
::
sflphone
::
PluginManager
::
instance
()
PluginManager
*
PluginManager
::
instance
()
{
if
(
!
_instance
){
return
new
PluginManager
();
...
...
@@ -14,28 +14,26 @@
return
_instance
;
}
::
sflphone
::
PluginManager
::
PluginManager
()
:
_loadedPlugins
()
PluginManager
::
PluginManager
()
:
_loadedPlugins
()
{
_instance
=
this
;
}
::
sflphone
::
PluginManager
::~
PluginManager
()
PluginManager
::~
PluginManager
()
{
_instance
=
0
;
}
int
::
sflphone
::
PluginManager
::
loadPlugins
(
const
std
::
string
&
path
)
PluginManager
::
loadPlugins
(
const
std
::
string
&
path
)
{
std
::
string
pluginDir
,
current
;
::
sflphone
::
Plugin
*
plugin
;
DIR
*
dir
;
dirent
*
dirStruct
;
int
result
=
0
;
void
*
handle
;
createFunc
*
createPlugin
;
LibraryManager
*
library
;
Plugin
*
plugin
;
const
std
::
string
pDir
=
".."
;
const
std
::
string
cDir
=
"."
;
...
...
@@ -52,22 +50,25 @@
current
=
dirStruct
->
d_name
;
/* Test if the current item is not the parent or the current directory */
if
(
current
!=
pDir
&&
current
!=
cDir
){
handle
=
loadDynamicLibrary
(
pluginDir
+
current
);
if
(
instanciatePlugin
(
handle
,
&
plugin
)
!=
0
)
/* Load the dynamic library */
library
=
loadDynamicLibrary
(
pluginDir
+
current
);
/* Instanciate the plugin object */
if
(
instanciatePlugin
(
library
,
&
plugin
)
!=
0
)
{
_debug
(
"Error instanciating the plugin ...
\n
"
);
return
1
;
}
/*
if(registerPlugin (
handle, interface
) != 0)
/*
Regitering the current plugin */
if
(
registerPlugin
(
plugin
,
library
)
!=
0
)
{
_debug
(
"Error registering the plugin ...
\n
"
);
return
1
;
}
*/
}
}
}
}
}
else
return
1
;
...
...
@@ -78,84 +79,134 @@
return
0
;
}
::
sflphone
::
Plug
in
*
::
sflphone
::
PluginManager
::
isPluginLoaded
(
const
std
::
string
&
name
)
in
t
PluginManager
::
unloadPlugins
(
void
)
{
if
(
_loadedPlugins
.
empty
())
return
NULL
;
PluginInfo
*
info
;
if
(
_loadedPlugins
.
empty
())
return
0
;
/* Use an iterator on the loaded plugins map */
pluginMap
::
iterator
iter
;
iter
=
_loadedPlugins
.
begin
();
while
(
iter
!=
_loadedPlugins
.
end
()
)
{
if
(
iter
->
first
==
name
)
{
/* Return the associated plugin */
return
iter
->
second
;
info
=
iter
->
second
;
if
(
deletePlugin
(
info
)
!=
0
)
{
_debug
(
"Error deleting the plugin ...
\n
"
);
return
1
;
}
unloadDynamicLibrary
(
info
->
_libraryPtr
);
if
(
unregisterPlugin
(
info
)
!=
0
)
{
_debug
(
"Error unregistering the plugin ...
\n
"
);
return
1
;
}
iter
++
;
}
/* If we are here, it means that the plugin we were looking for has not been loaded */
return
NULL
;
return
0
;
}
void
*
::
sflphone
::
PluginManager
::
loadDynamicLibrary
(
const
std
::
string
&
filename
)
bool
PluginManager
::
isPluginLoaded
(
const
std
::
string
&
name
)
{
if
(
_loadedPlugins
.
empty
())
return
false
;
/* Use an iterator on the loaded plugins map */
pluginMap
::
iterator
iter
;
iter
=
_loadedPlugins
.
find
(
name
);
void
*
pluginHandlePtr
=
NULL
;
const
char
*
error
;
/* Returns map::end if the specified key has not been found */
if
(
iter
==
_loadedPlugins
.
end
())
return
false
;
_debug
(
"Loading dynamic library %s
\n
"
,
filename
.
c_str
());
/* Returns the plugin pointer */
return
true
;
}
/* Load the library */
pluginHandlePtr
=
dlopen
(
filename
.
c_str
(),
RTLD_LAZY
);
if
(
!
pluginHandlePtr
)
{
error
=
dlerror
();
_debug
(
"Error while opening plug-in: %s
\n
"
,
error
);
return
NULL
;
}
dlerror
();
return
pluginHandlePtr
;
LibraryManager
*
PluginManager
::
loadDynamicLibrary
(
const
std
::
string
&
filename
)
{
/* Load the library through the library manager */
return
new
LibraryManager
(
filename
);
}
int
PluginManager
::
unloadDynamicLibrary
(
LibraryManager
*
libraryPtr
)
{
_debug
(
"Unloading dynamic library ...
\n
"
);
/* Close it */
return
libraryPtr
->
unloadLibrary
();
}
int
::
sflphone
::
PluginManager
::
instanciatePlugin
(
void
*
handlePtr
,
::
sflphone
::
Plugin
**
plugin
)
PluginManager
::
instanciatePlugin
(
LibraryManager
*
libraryPtr
,
Plugin
**
plugin
)
{
createFunc
*
createPlugin
;
LibraryManager
::
SymbolHandle
symbol
;
createPlugin
=
(
createFunc
*
)
dlsym
(
handlePtr
,
"create"
);
if
(
dlerror
()
)
{
_debug
(
"Error creating the plugin: %s
\n
"
,
dlerror
());
if
(
libraryPtr
->
resolveSymbol
(
"createPlugin"
,
&
symbol
)
!=
0
)
return
1
;
}
createPlugin
=
(
createFunc
*
)
symbol
;
*
plugin
=
createPlugin
();
return
0
;
}
int
::
sflphone
::
PluginManager
::
regis
te
r
Plugin
(
void
*
handlePtr
,
Plugin
*
plugin
)
PluginManager
::
dele
tePlugin
(
Plugin
Info
*
plugin
)
{
std
::
string
name
;
destroyFunc
*
destroyPlugin
;
LibraryManager
::
SymbolHandle
symbol
;
if
(
!
(
handlePtr
&&
plugin
!=
0
)
)
if
(
plugin
->
_libraryPtr
->
resolveSymbol
(
"destroyPlugin"
,
&
symbol
)
!=
0
)
return
1
;
name
=
plugin
->
getPluginName
();
/* Add the data in the loaded plugin map */
_loadedPlugins
[
name
]
=
plugin
;
destroyPlugin
=
(
destroyFunc
*
)
symbol
;
/* Call it */
destroyPlugin
(
plugin
->
_plugin
);
return
0
;
}
int
::
sflphone
::
PluginManager
::
unloadDynamicLibrary
(
void
*
pluginHandlePtr
)
PluginManager
::
registerPlugin
(
Plugin
*
plugin
,
LibraryManager
*
library
)
{
dlclose
(
pluginHandlePtr
);
dlerror
();
std
::
string
key
;
PluginInfo
*
p_info
;
if
(
plugin
==
0
)
return
1
;
p_info
=
new
PluginInfo
();
/* Retrieve information from the plugin */
plugin
->
initFunc
(
&
p_info
);
key
=
p_info
->
_name
;
//p_info->_plugin = plugin;
p_info
->
_libraryPtr
=
library
;
/* Add the data in the loaded plugin map */
_loadedPlugins
[
key
]
=
p_info
;
return
0
;
}
int
PluginManager
::
unregisterPlugin
(
PluginInfo
*
plugin
)
{
pluginMap
::
iterator
iter
;
std
::
string
key
;
key
=
plugin
->
_name
;
if
(
!
isPluginLoaded
(
key
))
return
1
;
iter
=
_loadedPlugins
.
find
(
key
);
_loadedPlugins
.
erase
(
iter
);
return
0
;
}
src/plug-in/pluginmanager.h
View file @
3cc24f26
...
...
@@ -6,19 +6,27 @@
* @brief Base class of the plugin manager
*/
#include
"
plugin
.h"
#include
"
librarymanager
.h"
#include
"global.h"
#include
<map>
#include
<string>
#include
<vector>
namespace
sflphone
{
class
PluginManager
{
class
Plugin
;
typedef
struct
PluginInfo
{
std
::
string
_name
;
LibraryManager
*
_libraryPtr
;
Plugin
*
_plugin
;
int
_major_version
;
int
_minor_version
;
}
PluginInfo
;
public:
#include
"plugin.h"
class
PluginManager
{
public:
/**
* Destructor
*/
...
...
@@ -34,46 +42,51 @@ namespace sflphone {
* @param path The absolute path to the directory
* @return int The number of items loaded
*/
int
loadPlugins
(
const
std
::
string
&
path
=
""
);
int
loadPlugins
(
const
std
::
string
&
path
=
""
);
int
instanciatePlugin
(
void
*
handlePtr
,
Plugin
**
plugin
);
int
unloadPlugins
(
void
);
int
instanciatePlugin
(
LibraryManager
*
libraryPtr
,
Plugin
**
plugin
);
/**
* Check if a plugin has been already loaded
* @param name The name of the plugin looked for
* @return
Plugin*
The pointer on the plugin or NULL if not found
* @return
bool
The pointer on the plugin or NULL if not found
*/
Plugin
*
isPluginLoaded
(
const
std
::
string
&
name
);
bool
isPluginLoaded
(
const
std
::
string
&
name
);
int
registerPlugin
(
void
*
handle
,
Plugin
*
plugin
);
int
registerPlugin
(
Plugin
*
plugin
,
LibraryManager
*
library
);
int
unregisterPlugin
(
PluginInfo
*
plugin
);
int
deletePlugin
(
PluginInfo
*
plugin
);
/**
* Load a unix dynamic/shared library
* @param filename The path to the dynamic/shared library
* @return
void
* A pointer on
i
t
* @return
LibraryManager
* A pointer on t
he library
*/
void
*
loadDynamicLibrary
(
const
std
::
string
&
filename
);
LibraryManager
*
loadDynamicLibrary
(
const
std
::
string
&
filename
);
/**
* Unload a unix dynamic/shared library
* @param
pluginHandleptr
The pointer on the loaded
plugin
* @param
LibraryManager*
The pointer on the loaded
library
*/
int
unloadDynamicLibrary
(
void
*
pluginHandlePtr
);
int
unloadDynamicLibrary
(
LibraryManager
*
libraryPtr
);
private:
private:
/**
* Default constructor
*/
PluginManager
();
/* Map of plugins associated by their string name */
typedef
std
::
map
<
std
::
string
,
Plugin
*>
pluginMap
;
typedef
std
::
map
<
std
::
string
,
Plugin
Info
*>
pluginMap
;
pluginMap
_loadedPlugins
;
/* The unique static instance */
static
PluginManager
*
_instance
;
};
}
}
;
#endif //PLUGIN_MANAGER_H
src/plug-in/test/pluginTest.cpp
View file @
3cc24f26
#include
"../plugin.h"
namespace
sflphone
{
class
PluginTest
:
public
Plugin
{
public:
PluginTest
(
const
std
::
string
&
name
)
:
Plugin
(
name
)
{
}
virtual
int
initFunc
(
int
i
)
{
return
i
;
#define MAJOR_VERSION 1
#define MINOR_VERSION 0
class
PluginTest
:
public
Plugin
{
public:
PluginTest
(
const
std
::
string
&
name
)
:
Plugin
(
name
)
{
}
};
}
virtual
int
initFunc
(
PluginInfo
**
info
)
{
(
*
info
)
->
_plugin
=
this
;
(
*
info
)
->
_major_version
=
MAJOR_VERSION
;
(
*
info
)
->
_minor_version
=
MINOR_VERSION
;
(
*
info
)
->
_name
=
getPluginName
();
return
0
;
}
};
extern
"C"
::
sflphone
::
Plugin
*
create
(
void
){
return
new
::
sflphone
::
PluginTest
(
"mytest"
);
extern
"C"
Plugin
*
create
Plugin
(
void
){
return
new
PluginTest
(
"mytest"
);
}
extern
"C"
void
destroy
(
::
sflphone
::
Plugin
*
p
){
extern
"C"
void
destroy
Plugin
(
Plugin
*
p
){
delete
p
;
}
test/pluginmanagerTest.cpp
View file @
3cc24f26
...
...
@@ -26,60 +26,70 @@
using
std
::
cout
;
using
std
::
endl
;
#define PLUGIN_TEST_DIR "/usr/lib/sflphone/plugins/libplugintest.so"
#define PLUGIN_TEST_NAME "mytest"
#define PLUGIN_TEST_DIR "/usr/lib/sflphone/plugins/"